Gorm 语法避坑

1. 方法参数是值传递,而不是引用传递,注意:slice、map、chan本身是指针,所以相当于引用传递,但数组是值传递代码语言:javascript代码运行次数:0运行复制type user struct {name string}fu

Gorm 语法避坑

1. 方法参数是值传递,而不是引用传递,注意:slice、map、chan本身是指针,所以相当于引用传递,但数组是值传递
代码语言:javascript代码运行次数:0运行复制
type user struct {
   name string
}

func main() {
   var u = user{name: "old name"}
   fmt.Println(u) // {old name}
   changeUserName(u) // 此处是值传递,所以u里的字段值不会被调用的方法所改变
   fmt.Println(u) // {old name}
}

func changeUserName(u user) {
   u.name = "new name"
}
  1. 创建给定大小的slice
代码语言:javascript代码运行次数:0运行复制
// 示范1:
var arr = make([]int, 2)
fmt.Println(len(arr), cap(arr), arr) // 2, 2, [0, 0]

// 示范2:
var arr = make([]int, 0, 2)
fmt.Println(len(arr), cap(arr), arr) // 0, 2, []
3. append方法会根据slice容量决定是否创建新slice
代码语言:javascript代码运行次数:0运行复制
// 示范1:
var arr = make([]int, 0)
append(arr, 10)
fmt.Println(arr) // []

arr = append(arr, 10) // 强烈推荐的写法
fmt.Println(arr) // [10]

// 示范2:
var arr = make([]int, 0, 2)
append(arr, 10)
fmt.Println(arr) // [10]
4. for-range上定义的变量,每次循环都不会改变变量的ptr,只会改变变量的值
代码语言:javascript代码运行次数:0运行复制
// 示范1:
func main() {
   arr1 := []int{1, 2, 3}
   arr2 := make([]*int, 0)
   for _, v := range arr1 {
      arr2 = append(arr2, &v) // 此时取的是变量v的ptr,而不是arr1中元素的ptr
   }
   for _, v := range arr2 {
      fmt.Print(*v)
   }
}
// 最后输出:333

// 示范2:
func main() {
   arr1 := []int{1, 2, 3}
   arr2 := make([]*int, 0)
   for _, v := range arr1 {
      t := v  // 变量t每轮循环都新定义一次,分别存了arr1中的元素复制值
      arr2 = append(arr2, &t)
   }
   for _, v := range arr2 {
      fmt.Print(*v)
   }
}
// 最后输出:123
5. 数组类型是包含数组大小的,不同大小的数组类型,是不同的类型,建议开发中使用slice而不是数组
代码语言:javascript代码运行次数:0运行复制
func main() {
   var arr1 [100]int
   var arr2 [200]int
   // 下面的代码是错的,arr1和arr2是不同的类型变量
   // arr2 = arr1
}
  1. 数组切slice后,会使得数组内存无法释放
代码语言:javascript代码运行次数:0运行复制
// 示范1:
func notGCSample() []int{
   var arr1 [100]int
   var slice = arr1[98:100]
   return slice
}
// 调用方拿到notGCSample返回值后,[100]int所占内存不会释放,因为slice底层数组使用的还是[100]int

// 示范2:
func canGCSample() []int{
   var arr1 [100]int
   var slice = make([]int, 2)
   copy(slice, arr1[98:100])
   return slice
}
// 调用方拿到notGCSample返回值后,[100]int所占内存会释放
7. func copy(dst, src []Type)第一个参数是dst,第二个参数是src,和Java的一般方法参数设计相反
8. 零值与nil
  1. nil不是关键字
  2. 各基础类型零值:数值类型 = 0,bool = false,string = ""
  3. struct、数组的零值是包含的字段都是零值
  4. ptr零值是nil,只要不涉及解析ptr的值,其他操作都可以
  5. slice零值是nil,slice零值不能索引操作,其他操作都可以
  6. map零值是nil,map零值可看作是只读空map,不能写入
  7. chan零值是nil,读写都会阻塞,不能close 1. 被close后的chan,恒可读(select会立刻返回零值+false标志位),不能写,不能close
  8. function零值是nil,不能调用
  9. interface底层由type和val组成,只有这两个都是nil,才是nil
9. 闭包中用到的局部变量会绑定到闭包
代码语言:javascript代码运行次数:0运行复制
// 示范1:
func getAddFunc() func() int {
   i := 0
   return func() int {
      i++
      return i
   }
}

func main() {
   f1 := getAddFunc()
   fmt.Println(f1()) // 1
   fmt.Println(f1()) // 2
   f2 := getAddFunc()
   fmt.Println(f2()) // 1
   fmt.Println(f2()) // 2
}

// 示范2:
func main() {
   wg := sync.WaitGroup{}
   wg.Add(5)
   for i := 0; i < 5; i++ {
      go func() {
         println(i)
         wg.Done()
      }()
   }
   wg.Wait()
}
// 最后输出:不一定,根据goroutine调度有关,可能是55555、45555、34555、35555等
  1. 值传递引用传递问题:接收器如果不是指针,也是值传递,而不是引用传递
代码语言:javascript代码运行次数:0运行复制
type user struct {
   name string
}

// 接收器是值传递而不是引用传递,所以原对象的字段值不会改变
func (u user) setUserNameByVal(name string) {
   u.name = name
}

// 使用指针作为接收器,引用的是原对象,所以会修改原对象的字段值
func (u *user) setUserNameByPtr(name string) {
   u.name = name
}

func main() {
   u := user{name: "old name"}
   fmt.Println(u) // {old name}
   u.setUserNameByVal("new name by val")
   fmt.Println(u) // {old name}
   u.setUserNameByPtr("new name by ptr")
   fmt.Println(u) // {new name by ptr}
}
11. for-range不要遍历大数组,应先创建数组的slice,然后遍历slice。因为for-range上定义的变量都是值传递,如果遍历数组,值传递相当于拷贝了一份相同数据的数组
代码语言:javascript代码运行次数:0运行复制
// 示范1:
var bigArr [10000]int
for i, v := range bigArr { // 此处相当于拷贝了一份bigArr
   // do something
}

// 示范2:
var bigArr [10000]int
for i, v := range bigArr[0:] { // 此处相当于拷贝了一份bigArr[0:]的slice
   // do something
}
12. 不能用'&'取址的情况
  1. const常量不能取址
  2. map的value、数组里的值不能取址(slice里的值可以取址)
13. map中的value如果是值而不是ptr,无法改变value里的字段值,可以取value里的字段值
代码语言:javascript代码运行次数:0运行复制
// 示范1:
valMap := map[string][3]int{"1": {1, 2, 3}}
valMap["1"][0] = 10 // error,因为数组是值
val := valMap["1"][0] // ok

// 示范2:
ptrMap := map[string][]int{"1": {1, 2, 3}}
ptrMap["1"][0] = 10 // ok,因为slice相当于指针
val := valMap["1"][0] // ok
14. gorm2.0 First 方法回返回错误:Not Found, 但是 Find 方法没查询到数据不返回任何错误
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。原始发表:2024-06-23,如有侵权请联系 cloudcommunity@tencent 删除gorm变量数组语法指针

发布者:admin,转转请注明出处:http://www.yc00.com/web/1748124685a4735194.html

相关推荐

  • Gorm 语法避坑

    1. 方法参数是值传递,而不是引用传递,注意:slice、map、chan本身是指针,所以相当于引用传递,但数组是值传递代码语言:javascript代码运行次数:0运行复制type user struct {name string}fu

    4小时前
    10

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信