Golang的指针赋值有没有更方便的方法?
type Test struct {
ID int64
Name *string
PWD string
Time time.Time
}
func main() {
t := new(Test)
name := "zhangsan"
t.Name = &name
fmt.Println(*t.Name)
}
这种指针赋值需要写两条语句,写起来麻烦,而且还要多定义一个变量,有没有更方便更好的写法呢?
我试了*t.Name="zhangsan"
不行,因为这种写法好像不是赋值,而是去修改地址的值,由于初始没有地址,所以报错了:
panic: runtime error: invalid memory address or nil pointer dereference
大家有没有更好的赋值方式?
共 22 个回复
stevewang
需要两条语句,但是不需要多定义一个变量:
另外,一般很少需要用到
*string
类型。你为什么不直接使用string
呢?shook
@stevewang 还不是为了判断结构里面哪个字段没有数据,golang都有默认值,要想判断哪个字段为空我知道的方法就是判断指针为nil,不知道你有没有更好的方法。
stevewang
@shook
database/sql
有个NullString
类型,也许你可以直接使用。shook
@stevewang 应该不是这个,因为还没到数据库的层面呢,还只是判断结构体的数据。
stevewang
我的意思是,你可以直接使用
NullString
类型根据Valid的值来处理nil的情况,不是一定要用数据库。或者把那个类型的定义复制到自己的包里 也可以。shook
哦,这样哈,那我晚上试试。
shook
@stevewang 看了一下,没搞懂怎么用…isValid()出来的值都是true,没法用Valid的指来处理nil…
stevewang
Valid值是你自己设置的,如果字符串是nil,Valid就设置为false,否则设置为true。
shook
这也是一个办法,只是处理起来也不是很方便,现在有两个办法了,我想想做哪一种,谢谢哈!
ssqq
字符串不需要引用,第一因为字符串不能修改,第二因为系统会自动优化传递字符串参数,和指针差不多。参看 <<Go语言程序设计>> 109 页。
“go 语言编译器会将传递过程进行安全的优化,因此无论传递的字符串长度多少,实际传递的数据量都会非常小,每个字符串的代码在64位机器上大概是16个字节,在32位的机器上大概是8字节。但如果修改一个字符串,就必须创建新的字符串。代码可能非常大。”
stevewang
*string
相当于多了一次指针访问,性能上会稍微差一些;另外如果数量很多的话,GC压力也会增加,因为要额外在堆上创建很多的string
对象。shook
@ssqq 嗯,我只是拿字符串来举例,其实也不是为了要去改它,只是想通过它来判断Struct的某个字段是否有值而已,没其他办法的情况下才想这么干的,就是感觉Golang判断值为空好麻烦,都有默认值!
shook
@stevewang 用了其他的ORM总感觉被强加了很多东西,就想自己写个适合自己的ORM,其他的地方都勉强做好了,但是在update这儿卡了几天了,一直没个好办法来判断哪些Struct字段有值(我设想的是增删改查都传Struct)。
huangxianghan
字段类型 设为interface{} 就可以放nil了,如果怕取值麻烦可以学西java的包装类。
每个基本类型都自己定义一个包装类型。
huangxianghan
shook
@huangxianghan 非常感谢您的回复,你的解决方法又给了我一个思路,你的方式和@stevewang的方式差不多,都是自定义类型和方法,看来只有从这个方面找出路了。
imjj
加个函数也许方便一些
shook
@imjj 厉害,你的回答简直是完美解决了我开始提出的问题!这么简单我居然都想不到…
虽然我现在可能会用其他办法做这个事情,但是你的答案绝对是我开始最想要的答案!
shook
不过写了ORM才觉得Golang有的地方真的挺烦的,一个数据类型还不能从头用到底,数据开始定义为String,不能直接判断空值是第一个坑,从数据库读出来的数据得换成NullString或者RawByte之类的,不然读到空值会Panic,这是第二个坑,最后还得换回原类型,换来换去的,一不注意就出问题了。
感觉Golang对新手真的不怎么友好,经常遇到坑,当然我目前也只认真学过Golang,其他语言也不会,不知道其他语言是不是也这样。以前只是会SQL写写报表啥的。
joeonly
问题是解决了,但为取字符串地址加一个方法总有点别扭吧?我更愿意加个工厂方法。
另外大家为什么那么喜欢 new 一个东西,是为了直观吗?如果不是,个人感觉如果不加工厂方法,是不是用
&Test{Name: StringPtr("zhangsan")}
更方便?
个人觉得 GO 的上面这种写法比 JAVA 构造函数的方式还方便,想初始化哪个字段就初始化哪个,不用搞那么多重载。
jong1985
楼主,我自己也写了一个orm,大家交流交流
https://github.com/shengzhi/shorm
shook
@jong1985 我只是试着做了一下,连成品都没有,去拜读拜读你的源码。