自定义类型
在go语言中,用户可以自定义类型。类似于C语言中的结构体,go语言中使用struct来定义自定义的类型。
创建自定义类型
package main
import (
"fmt"
)
//自定义类型
type person struct{
id int
name string
age int
}
func main(){
var p person
fmt.Println("id=",p.id,",name=",p.name,",age=",p.age)
}
//id= 0 ,name= ,age= 0
复制代码
上面的代码定义了一个自定义的person类型,因为没有给p赋值,所以p里面的所有属性都是默认值。
package main
import (
"fmt"
)
//自定义类型
type person struct{
id int
name string
age int
}
func main(){
p := person{
id:1,
name:"zhongzhong",
age:25,
}
fmt.Println("id=",p.id,",name=",p.name,",age=",p.age)
}
//id= 1 ,name= zhongzhong ,age= 25
复制代码
上面的代码声明并且初始化了person类型的变量p,注意,初始化的时候,每一行后面以逗号结尾,最后一行也必须要逗号结尾,否则会报错。
package main
import (
"fmt"
)
//自定义类型
type person struct{
id int
name string
age int
}
func main(){
p := person{1,"zhongzhong",25}
fmt.Println("id=",p.id,",name=",p.name,",age=",p.age)
}
复制代码
上面的代码使用了另一种方式来初始化p,在{}中直接使用属性的值来初始化,而不需要指定属性的名称。每个属性的值使用逗号隔开,注意,末尾没有逗号。 这种写法,属性的值必须和属性的顺序一致。
方法
在go语言中,方法也是函数,但是方法的声明和函数的声明有些差异,在声明方法的时候,必须在func关键字和函数名称之间加一个参数,这个参数用来表示这个方法的接收者,看下面的代码:
package main
import (
"fmt"
)
//自定义类型
type person struct{
id int
name string
age int
}
//声明了一个函数
func fn(){
fmt.Println("这是一个函数")
}
//声明一个函数,函数有一个string类型的参数
//函数的返回值有两个,第一个是一个string类型的值
//第二个是一个int类型的值
func fn1(name string) (string,int){
return "",0
}
//声明了一个方法,这个方法的接受者为person
func (p person) hello(){
fmt.Println("hello,我是",p.name)
}
func main(){
//调用函数
fn()
p := person{1,"zhongzhong",25}
//调用方法
p.hello()
}
//这是一个函数
//hello,我是 zhongzhong
复制代码
从上面的代码中可以看出,方法需要指定一个方法的接收者,也就是在将来调用的方法的是什么类型。可以理解为,一个方法声明的时候,就已经知道了,这个方法属于哪种类型,而且只能被指定的类型所调用。
package main
import (
"fmt"
)
//自定义类型
type person struct{
id int
name string
age int
}
//声明了一个方法,这个方法的接受者为person
func (p person) changeName(){
p.name = "new name"
}
//声明第二个方法,这个方法的接受者为*person
func (p *person) changeName2(){
p.name = "new name2"
}
func main(){
p := person{1,"zhongzhong",25}
p.changeName()
fmt.Println(p.name)
p.changeName2()
fmt.Println(p.name)
}
//zhongzhong
//new name2
复制代码
在声明的代码中,第二个方法声明有点特殊,方法的接受者为person类型的指针,然后我们在main中分别调用了changeName和changeName2两个方法,可以发现changeName并没有改变name的值 而changName2改变了name的值。这是因为changeName中传递的是p的拷贝,而在changeName2中传递个是p的内存地址,所以对于changeName2这个方法的接受者参数的修改,都会反应到p上面。
问题:changeName2中的接收者类型明明是要给指针,而我们传递给它的却是一个person类型的值,并不是一个指针,那么为什么也可以正常调用呢?
这是因为在go语言中,会自动对接受者做出调整,上面的代码p.changeName2()在go语言处理之后, 会变成(&p).changeName2()来调用,这样就符合了changeName2声明的接受者参数的类型了,调用自然也就成功了。
总结:
在这篇文章中我们讲解了如何使用struct关键字定义自定义类型, 以及如何通过方法来扩展自定义类型。还讲解了方法的接受者为值和指针时的区别。