struct为何物
go中的struct可以实现oop中的类、方法。go语言中的struct成员可以是任何类型,如普通类型、复合类型、函数、struct、interface等。
入门
//定义
type User struct {
name string
email string
password string
}
//声明
var user User
var userref *User
fmt.Println(user) //{} 默认初始化为零值
fmt.Println(userref) //<nil> 未初始化
userref = new(User)
fmt.Println(userref) //&{ }
//初始化
user = User{name: "liming", email: "liming@gamil.com", password: "pw123456"}
userref = &User{name: "liming", email: "liming@gamil.com", password: "pw123456"}
fmt.Println(user) //{liming liming@gamil.com pw123456}
fmt.Println(userref) //&{liming liming@gamil.com pw123456}
//简单写法
user1 := User{name: "liming", email: "liming@gamil.com", password: "pw123456"}
userref1 := &User{name: "liming", email: "liming@gamil.com", password: "pw123456"}
fmt.Println(user1) //{liming liming@gamil.com pw123456}
fmt.Println(userref1) //&{liming liming@gamil.com pw123456}
//引用与值的区别
upUser(user1)
upUser(userref1)//cannot use userref1 (type *User) as type User in argument to upUser
upUserRef(userref1)
fmt.Printf("name is %s, %s", user1.name, userref1.name) //name is liming, LIMING
//递归struct
type LinkedNode struct {
data string
su *LinkedNode
}
type DoubleLinkedNode struct {
pr *DoubleLinkedNode
data string
su *DoubleLinkedNode
}
type TreeNode struct {
le *TreeNode
data string
ri *TreeNode
}
进阶
构造方法
oop中 , new Object(),go 通过工厂方法 NewStructName
//不强制使用构造函数,首字母大写
type File struct {
fd int
filename string
}
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
return &File{fd, name}
}
//强制使用构造函数,首字母小写
type file1 struct {
fd int
filename string
}
func NewFile1(fd int, name string) *file1 {
if fd < 0 {
return nil
}
return &file1{fd, name}
}
tag
可以为struct域加说明,这些说明可以通过反射获取
type TagType struct { // tags
field1 bool “An important answer”
field2 string “The name of the thing”
field3 int “How much there are”
}
匿名域
每种类型只能有一个匿名域。可以用来实现oop中的继承
type anonymousStruct struct {
name string
int
string
File
}
anonymous := new(anonymousStruct)
anonymous.name = "hanmeimei"
anonymous.int = 88
anonymous.string = "english"
anonymous.File.fd = 10 // or anonymous.fd = 10
anonymous.File.filename = "xxoo.avi" //or anonymous.filename = "xxoo.avi"
fmt.Println(anonymous) //&{hanmeimei 88 english {10 xxoo.avi}}
方法
go语言中的oop很另类,类在go里面叫做receiver,receiver可以是除了interface之外的任何类型。方法和类并非组织在一起,传统的oop方法和类放在一个文件里面,而go语言只要在同一个包里就可,可分散在不同文件里。go的理念就是数据和实现分离
Methods are not mixed with the data definition (the structs): they are orthogonal to types; representation(data) and behavior (methods) are independent
go方法定义格式如下
func (recv receiver_type) methodName(parameter_list) (return_value_list) { … }
func (_ receiver_type) methodName(parameter_list) (return_value_list) { … }
func (this receiver_type) methodName(parameter_list) (return_value_list) { … }
func (self receiver_type) methodName(parameter_list) (return_value_list) { … }
oop调用 object.method ,go调用recv.Method()
定义非struct类型方法
type IntVector []int
func (v IntVector) Sum() (s int) {
for _, x := range v {
s += x
}
return
}
方法作用域
method和receiver必须在同一个包里定义
import “container/list”
//cannot define new methods on non-local type list.List
func (p *list.List) Iter() {
// …
}
hack方法
//hack
type myList struct {
list.List //anonymous field
}
func (p *myList) Iter() {
// …
}
reciever
reciever最好定义成指针的形式。对已非指针形式的reciever会自动转换成指针形式。如
func (u *User) Iter() {
// …
}
u:=User{"liming",22}
u.Iter() //会转换成&User
getter setter
type Person struct {
firstName string
lastName string
}
func (p *Person) FirstName() string {
return p.firstName
}
func (p *Person) SetFirstName(newName string) {
p.firstName = newName
}