mirror of
https://gitlab.com/game-loader/hugo.git
synced 2025-04-20 05:52:07 +08:00
golang note update
This commit is contained in:
parent
f0d7c6a4e0
commit
8ed9ed06f3
@ -5,23 +5,26 @@ date: 2022-11-08
|
|||||||
categories: ["开发"]
|
categories: ["开发"]
|
||||||
draft: false
|
draft: false
|
||||||
tags: []
|
tags: []
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
1. [golang语言问题](#golang语言问题)
|
1. [golang语言问题](#golang语言问题)
|
||||||
* [slice传参](#slice传参)
|
- [slice传参](#slice传参)
|
||||||
* [修改slice中struct的问题](#修改slice中struct的问题)
|
- [修改slice中struct的问题](#修改slice中struct的问题)
|
||||||
|
|
||||||
# golang后端开发笔记
|
# golang后端开发笔记
|
||||||
|
|
||||||
之前的小程序使用的是原生的云开发,方便固然方便但实际上并没有做太多的工作,也不需要考虑过多的问题,这次用golang重写后端算是对自身的一个挑战,从头梳理后端开发的基本内容并且深入理解golang语言和网络相关的知识。
|
之前的小程序使用的是原生的云开发,方便固然方便但实际上并没有做太多的工作,也不需要考虑过多的问题,这次用golang重写后端算是对自身的一个挑战,从头梳理后端开发的基本内容并且深入理解golang语言和网络相关的知识。
|
||||||
主要使用gin+gorm+Mysql+Redis
|
主要使用gin+gorm+Mysql+Redis
|
||||||
|
|
||||||
## golang语言问题
|
## golang语言问题
|
||||||
|
|
||||||
### slice传参
|
### slice传参
|
||||||
|
|
||||||
### 修改slice中struct的问题
|
### 修改slice中struct的问题
|
||||||
|
|
||||||
在修改slice中的数据时,自然会想到用for range循环。但在实际使用的过程中需要注意golang语言中range循环的一些特性。下面给出一个例子
|
在修改slice中的数据时,自然会想到用for range循环。但在实际使用的过程中需要注意golang语言中range循环的一些特性。下面给出一个例子
|
||||||
```go
|
|
||||||
|
```go
|
||||||
func main() {
|
func main() {
|
||||||
slice := []int{10, 20, 30, 40}
|
slice := []int{10, 20, 30, 40}
|
||||||
for index, value := range slice {
|
for index, value := range slice {
|
||||||
@ -29,18 +32,21 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
这里value如果代表的是slice切片中的各个数据,那么value的地址理应随着循环发生变化,但是实际上输出的结果为
|
这里value如果代表的是slice切片中的各个数据,那么value的地址理应随着循环发生变化,但是实际上输出的结果为
|
||||||
> value = 10 , value-addr = c4200aedf8 , slice-addr = c4200b0320
|
|
||||||
|
> value = 10 , value-addr = c4200aedf8 , slice-addr = c4200b0320
|
||||||
>
|
>
|
||||||
> value = 20 , value-addr = c4200aedf8 , slice-addr = c4200b0328
|
> value = 20 , value-addr = c4200aedf8 , slice-addr = c4200b0328
|
||||||
>
|
>
|
||||||
> value = 30 , value-addr = c4200aedf8 , slice-addr = c4200b0330
|
> value = 30 , value-addr = c4200aedf8 , slice-addr = c4200b0330
|
||||||
>
|
>
|
||||||
> value = 40 , value-addr = c4200aedf8 , slice-addr = c4200b0338
|
> value = 40 , value-addr = c4200aedf8 , slice-addr = c4200b0338
|
||||||
|
|
||||||
显然value的地址并没有发生变化,这说明value本身是一个结构,在循环过程中只是将对应的值拷贝到了value当中,value并不是指向切片中对应值的指针。
|
显然value的地址并没有发生变化,这说明value本身是一个结构,在循环过程中只是将对应的值拷贝到了value当中,value并不是指向切片中对应值的指针。
|
||||||
关于这点,在golang的官方wiki中的CommonMistakes中给出了相关的说明,官方给出的例子如下
|
关于这点,在golang的官方wiki中的CommonMistakes中给出了相关的说明,官方给出的例子如下
|
||||||
```go
|
|
||||||
|
```go
|
||||||
func main() {
|
func main() {
|
||||||
var out []*int
|
var out []*int
|
||||||
for i := 0; i < 3; i++ {
|
for i := 0; i < 3; i++ {
|
||||||
@ -50,27 +56,33 @@ func main() {
|
|||||||
fmt.Println("Addresses:", out[0], out[1], out[2])
|
fmt.Println("Addresses:", out[0], out[1], out[2])
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
官方给出的例子也非常有趣,这个例子实际上的输出结果为
|
官方给出的例子也非常有趣,这个例子实际上的输出结果为
|
||||||
|
|
||||||
> Values: 3 3 3
|
> Values: 3 3 3
|
||||||
>
|
>
|
||||||
> Addresses: 0x40e020 0x40e020 0x40e020
|
> Addresses: 0x40e020 0x40e020 0x40e020
|
||||||
|
|
||||||
在Go中,循环过程中的循环迭代器如第二个例子中的i以及第一个例子中的value都是一个单独的变量,在循环进行过程中会将不同的值拷贝给这个变量,这样的好处在于只需要为这个变量申请一次内存空间,之后改变它的值就可以了。但是因为只是将不同的值赋给这一个变量,该变量的地址一直没有变化,这时我们将该变量的地址放入out切片中,则最后通过解引用取得的值是该变量最后一次被赋予的值。即循环过程可以理解为
|
在Go中,循环过程中的循环迭代器如第二个例子中的i以及第一个例子中的value都是一个单独的变量,在循环进行过程中会将不同的值拷贝给这个变量,这样的好处在于只需要为这个变量申请一次内存空间,之后改变它的值就可以了。但是因为只是将不同的值赋给这一个变量,该变量的地址一直没有变化,这时我们将该变量的地址放入out切片中,则最后通过解引用取得的值是该变量最后一次被赋予的值。即循环过程可以理解为
|
||||||
```go
|
|
||||||
|
```go
|
||||||
func main(){
|
func main(){
|
||||||
var new_variable int
|
var new_variable int
|
||||||
var out []*int
|
var out []*int
|
||||||
// 模拟循环的过程
|
// 模拟循环的过程
|
||||||
new_variable = 1
|
new_variable = 1
|
||||||
append(out, &new_variable)
|
append(out, &new_variable)
|
||||||
new_variable = 2
|
new_variable = 2
|
||||||
append(out, &new_variable)
|
append(out, &new_variable)
|
||||||
new_variable = 3
|
new_variable = 3
|
||||||
append(out, &new_variable)
|
append(out, &new_variable)
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
这样一来这个循环最后的结果就很容易理解了。这个问题看似是一个小问题,但在实际编写程序的过程中常常会因疏忽这个问题而出错,比如在遍历一个结构体切片时,赋值给迭代器的成员变量,循环结束后会发现结构体切片中的值并没有改变,实际上应该使用诸如out[i]这种通过下标访问的形式修改切片中的值,而不是使用迭代器。这点要时刻注意
|
这样一来这个循环最后的结果就很容易理解了。这个问题看似是一个小问题,但在实际编写程序的过程中常常会因疏忽这个问题而出错,比如在遍历一个结构体切片时,赋值给迭代器的成员变量,循环结束后会发现结构体切片中的值并没有改变,实际上应该使用诸如out[i]这种通过下标访问的形式修改切片中的值,而不是使用迭代器。这点要时刻注意
|
||||||
|
|
||||||
|
### 使用的三方库更新问题
|
||||||
|
|
||||||
|
使用gorm时使用它的<a href="https://gorm.io/zh_CN/docs/update.html#%E4%BD%BF%E7%94%A8-SQL-%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%9B%B4%E6%96%B0">sql表达式更新</a>功能时发现会出现莫名其妙的bug, 更新表达式是减但是得到的sql语句是直接置零. 让我非常不解, 在研究文档的过程中, 我偶然发现当前的gorm文档是gorm 2.0,而我之前导入的包是gorm 1.0的包. 因此之前的1.0中可能并没有实现这个功能, 非常的尴尬. 将导入的包切换为gorm 2.0后一切功能正常.
|
||||||
|
|
||||||
|
这提醒我们在使用三方库时, 可能三方库会因为更新等原因有一些api上的重大变化, 要注意使用的包的版本.
|
||||||
|
Loading…
Reference in New Issue
Block a user