Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性,结构体是类型中带有成员的复合类型,属于值类型。
Go 语言中的类型可以被实例化,使用new()
或&
可以实例化该类型、获取实例的指针。
结构体成员是由一系列的成员变量构成,这些成员变量也被称为字段。字段有以下特性:
同样对于可见性,结构体的名称、结构体字段、结构体方法的名称首字母大小写规则和方法、变量名称规则相同。
使用关键字type
可以将各种基本类型定义为自定义类型,基本类型包括int、string、bool等。
结构体是一种复合的基本类型,通过type
定义为自定义类型后,使结构体更便于使用。
type structName struct {
filed1Name filed1Type
filed2Name filed2Type
filed3Name filed3Type
}
structName
:表示自定义结构体的名称,在同一个包内不能重复。struct{}
:表示结构体类型,type structName struct{}
可以理解为将 struct{}
结构体定义为structName
的类型。filed1Name、filed2Name
:表示结构体字段名,结构体中的字段名必须唯一。filed1Type、filed2Type
:表示结构体各个字段的类型。type Stu struct {
name string
age int
}
由于结构体属于基本数据类型(值类型),所以在声明时,系统会自动对结构体以及结构体字段赋零值
使用var
关键字
var s Stu
fmt.Println(s) // main.Stu{name:"", age:0}
sp := new(Stu)
s := *sp
fmt.Printf("%#v\n", s) // main.Stu{name:"", age:0}
可以在大括号中以键值对或成员声明顺序的方式进行赋值
s1 := Stu{}
fmt.Printf("%#v\n", s1) // main.Stu{name:"", age:0}
s2 := Stu{"lucy", 18}
fmt.Printf("%#v\n", s2) // main.Stu{name:"lucy", age:18}
s3 := Stu{name: "tom", age: 25}
fmt.Printf("%#v\n", s3) // main.Stu{name:"tom", age:25}
// 这种方法也可以直接获取结构体指针
s := &Stu{"lucy", 18}
fmt.Printf("%T\n", s) // *main.Stu
fmt.Printf("%#v\n", s) // &main.Stu{name:"lucy", age:18}
结构体变量和结构体指针都可以使用操作符.
对进行读写操作
package main
import "fmt"
type Stu struct {
name string
age int
}
func main() {
s := Stu{"lucy", 18}
s.name = "tom"
fmt.Println(s) // {tom 18}
sp := &s
sp.name = "lily"
fmt.Println(s) // {lily 18}
}
在Go语言中,没有类的概念但是可以给结构体、自定义类型定义方法。Go 方法是作用在接收者(receiver)上的一个函数,接受者就是结构体、自定义类型的实例,类似于其他语言中的this
或self
。
使用接收者,就可以直接在实例后使用.
来调用方法,并且操作实例
非本地类型不可定义方法,也就是不可以给别的包的类型定义方法。
package main
import (
"fmt"
)
type Stu struct {
name string
age int
}
// 定义结构体Stu的方法
func (s *Stu) ShowInfo() {
fmt.Printf("the user name is %v, age is %d\n", s.name, s.age)
}
func main() {
s := Stu{"lucy", 18}
s.ShowInfo() // the user name is lucy, age is 18
}
s
,Connector 类型的接收器变量应该命名为c
等。在Java里面,实例的信息字符串一般由toString
方法提供,在go里面,是由String() string
函数提供,其原理也是实现了接口的方法
package main
import (
"fmt"
)
type Stu struct {
name string
age int
}
func (s Stu) String() string {
return fmt.Sprintf("the user name is %v, age is %d\n", s.name, s.age)
}
func main() {
s := Stu{"lucy", 18}
fmt.Println(s) // the user name is lucy, age is 18
fmt.Println(&s) // the user name is lucy, age is 18
}
结构体可以包含一个或多个匿名(或内嵌)字段,即这些字段没有显式的名字,只有字段的类型是必须的,此时类型也就是字段的名字。
package main
import "fmt"
type Stu struct {
int
string
}
func main() {
s := Stu{18, "lucy"}
fmt.Println(s.int, s.string) // 18 lucy
}
Go语言中的继承是通过内嵌或组合来实现的
同样地结构体也是一种数据类型,所以它也可以作为一个匿名字段来使用。内层结构体被简单的插入或者内嵌进外层结构体,外层结构体实例可以直接访问内嵌结构体成员。这个简单的“继承”机制提供了一种方式,使得可以从另外一个或一些类型继承部分或全部实现。
内嵌结构体可以对外层的结构体进行功能增强,外层结构体可以直接调用内层的方法
package main
import "fmt"
type Father struct {
name string
age int
}
type Chil struct {
id int
Father
}
func main() {
c := Chil{111, Father{"lucy", 18}}
fmt.Printf("id:%d,name:%s,age:%d", c.id, c.name, c.age)
}
Go语言的结构体内嵌有如下特性:
在java里面,实例的信息字符串一般由toString方法提供,在go里面,是由String() string
函数提供,其原理也是实现了接口的方法
package main
import (
"fmt"
)
type Stu struct {
name string
age int
}
func (s Stu) String() string {
return fmt.Sprintf("the user name is %v, age is %d\n", s.name, s.age)
}
func main() {
s := Stu{"lucy", 18}
fmt.Println(s)
fmt.Println(&s)
}