結構體
結構體的基本概念
- 什么是結構體
- Go語言中的結構體幾乎和C語言中的結構體一模一樣都需要先定義結構體類型, 再定義結構體變量都是用來保存一組不同類型數據的
- 定義結構體類型格式:
type 結構體類型名稱 struct{
屬性名稱 屬性類型;
屬性名稱 屬性類型;
} - 定義結構體變量格式:
var 結構體變量名稱 結構體類型名稱
結構體初始化
注意點: 和切片以及字典不一樣, 結構體變量定義之后就可以直接使用了
//1.定義一個結構體
//1.1定義結構體類型
type Person struct {
name string
age int
}
//1.2定義結構體變量(先定義后初始化)
var per Person
//1.3操作結構體
//切片和字典定義變量后必須初始化才能使用
//結構體變量定義完成后不需要初始化可以直接使用
per.name = "lnj"
per.age = 18
fmt.Println(per)
- 先定義結構體變量再初始化
//3.先定義結構體變量再初始化
//定義結構體類型
type Person struct {
name string
age int
}
//定義結構體變量
var per Person
//給結構體完全初始化
per = Person{"wjh",19}
//給結構體部分初始化
//注意點: 部分初始化必須通過屬性名稱指定要給誰初始化
per = Person{age : 18}
fmt.Println(per)
- 定義結構體變量的同時初始化
//2.定義結構體變量一次性初始化
//定義一個結構體類型
type Person struct {
name string
age int
}
//定義結構體變量一次性初始化
var per Person = Person{"lnj",18}
//結構體變量名稱后面可以省略結構體類型
var per = Person{"lnj",18}
//可以使用語法糖來定義同時一次性初始化
per := Person{"lnj",18}
fmt.Println(per)
結構體值傳遞
package main
import "fmt"
//定義一個結構體
type Person struct {
name string
age int
}
func main() {
/*
結構體和數組一樣,都是值傳遞
作為函數的參數,在函數內部修改值不會影響到外面實參的值
*/
per1 := Person{"wjh", 19}
var per2 Person
//將結構體變量per1的值傳遞給per2
per2 = per1
per2.name = "lnj"
fmt.Println(per1)//{wjh 19}
//修改結構體變量per2的值不會影響per1中的值
fmt.Println(per2)//{lnj 19}
per := Person{"lnj", 10}
//結構體作為函數的參數,在函數內部修改值不會影響到外面實參的值
change(per)
fmt.Println(per)
}
func change(per Person) {
per.name = "haha"
}
復雜結構體
package main
import "fmt"
func main() {
/*
復雜的結構體
*/
type Person struct {
name string //字符串
age int //整型
score float64 //浮點型
arr [3]int //數組類型
sce []int //切片類型
dict map[string]string //字典類型
}
//普通類型結構體屬性都可以直接操作,不需要初始化
var per Person
per.name = "lnj"
per.age = 18
per.score = 80.5
per.arr[0] = 10
per.arr[1] = 20
per.arr[2] = 30
//{lnj 18 80.5 [10 20 30] [] map[]}
//切片和字典類型的必須要先初始化才可以使用
//創(chuàng)建切片
//per.sce = []int{10,20,30}
//注意點: 使用索引方式,不能超過切片的長度
per.sce = make([]int,3)
per.sce[0]= 10
per.sce[1]= 20
per.sce[2]= 30
//創(chuàng)建字典
per.dict = make(map[string]string,2)
per.dict["name"] = "wjh"
per.dict["age"] = "18"
//per.dict = map[string]string{"name":"wjh","age" :"18"}
fmt.Println(per)
}
結構體轉換
注意點:結構體變量之間可以相互轉換, 但是必須保證結構體類型的屬性名稱 屬性類型 屬性順序 屬性的個數 都一樣
package main
import "fmt"
func main() {
/*
結構體變量之間可以相互轉換, 但是必須保證結構體類型的
屬性名稱 屬性類型 屬性順序 屬性的個數 都一樣
*/
type Person1 struct {
name string
age int
}
//屬性順序不同
type Person2 struct {
age int
name string
}
//屬性名稱不同
type Person3 struct {
name string
score int
}
//屬性類型不同
type Person4 struct {
name string
score float64
}
//屬性的個數不同
type Person5 struct {
name string
age int
score float64
}
//屬性順序不同不能強轉
//var per2 Person2
//per2 = Person1(per2)
//fmt.Println(per2)
//屬性名稱不同不能強轉
//var per3 Person3
//per3 = Person1(per3)
//fmt.Println(per3)
//屬性類型不同不能強轉
var per4 Person4
per4 = Person1(per4)
fmt.Println(per4)
//屬性個數不同不能強轉
var per5 Person5
per5 = Person1(per5)
fmt.Println(per5)
}
匿名結構體
- 什么是匿名結構體屬性?
沒有名稱的屬性就是匿名屬性 - 如何操作匿名屬性?
匿名屬性的數據類型就是匿名屬性的名稱, 所以可以通過匿名屬性的數據類型來操作 - 匿名屬性一般都用于結構體的嵌套定義,結構體的屬性又是一個結構體
package main
import "fmt"
func main() {
type Person struct {
string //匿名結構體屬性
int
}
var per Person
per.string = "wjh" //可以通過匿名屬性的數據類型來操作
per.int = 18
fmt.Println(per)
type Date struct {
year int
month int
day int
}
type Person struct {
name string
age int
Date //結構體嵌套定義
}
type Animal struct {
name string
age int
Date
}
//使用結構體嵌套
var per Person
per.name = "wjh"
per.age = 19
per.Date = Date{2007,10,23} //{wjh 19 {2007 10 23}}
fmt.Println(per)
//定義結構體變量同時直接初始化
ani := Animal{"wawa",10,Date{2003,10,23}}
fmt.Println(ani)//{wawa 10 {2003 10 23}}
}
結構體嵌套的方式
-
第一種方式(雙重嵌套)
type 結構體名稱1 struct{}
type 結構體名稱2 struct{
結構體名稱1
}
//1.第一種方式
// 結構體和嵌套的結構體沒有重名屬性的情況
type Person struct {
name string
age int
}
type Student struct {
Person
score float64
}
//定義同時初始化結構體
stu := Student{Person{"wjh", 19}, 86.6}
fmt.Println(stu)
////1.1結構體嵌套定義,第一種操作結構體方法
//stu.Person.name = "lnj"
//stu.Person.age = 30
//fmt.Println(stu)
//1.2第二種操作結構體方法
//會先去Student結構體中查詢有沒有name屬性, 如果有就直接訪問
//如果沒有會繼續(xù)查找嵌套的匿名結構體中有沒有, 如果有就訪問匿名結構體中的name屬性
stu.name = "zs" //嵌套結構體屬性不重名可以直接訪問
stu.age = 20
fmt.Println(stu)
//2.第一種方式有重名屬性的情況
//結構體和嵌套的結構體有重名屬性的情況
type Person struct {
name string
age int
}
type Student struct {
Person
name string
score float64
}
//定義同時初始化結構體
stu := Student{Person{"wjh",19},"lnj", 90.3}
fmt.Println(stu) //{{wjh 19} lnj 90.3}
//2.1結構體嵌套定義,操作結構體的第一種方法
//注意點: 如果結構體與嵌套的結構體屬性有重名,使用這種方法操作數據,不會更改嵌套結構體中的同名屬性
stu.name = "haha"
fmt.Println(stu) //{{wjh 19} haha 90.3}
//2.2結構體嵌套定義,操作結構體第二種方法
//注意點: 如果結構體與嵌套的結構體屬性有重名,應該先指定結構體類型在指定結構體屬性
stu.Person.name = "zs"
stu.age = 30
fmt.Println(stu) //{{zs 30} haha 90.3}
- 第二種方式(三重嵌套)
type 結構體名稱1 struct{
}
type 結構體名稱2 struct{
結構體名稱1
}
type 結構體名稱3 struct{
結構體名稱2
}
//第二種方式
//1.沒有重名屬性
type Object struct {
name string
}
type Person struct {
Object
age int
}
type Student struct {
Person
score float32
}
//定義變量同時初始化
stu := Student{Person{Object{"wjh"}, 19}, 87.3}
fmt.Println(stu) //{{{wjh} 19} 87.3}
//操作結構體第一種方法
stu.name = "zs"
stu.age = 30
stu.score = 50.3
fmt.Println(stu) //{{{zs} 30} 50.3}
//操作結構體第二種方法
stu.Person.Object.name = "lnj"
stu.Person.age = 50
fmt.Println(stu) //{{{lnj} 50} 50.3}
//有重名屬性的情況
type Object struct {
name string
}
type Person struct {
Object
name string
age int
}
type Student struct {
Person
name string
score float32
}
//定義變量同時初始化
stu := Student{Person{Object{"wjh"},"lnj",13},"niuzi",39.2}
fmt.Println(stu) //{{{wjh} lnj 13} niuzi 39.2}
//操作結構體方法
//注意點: 如果不先指定結構體類型,只會操作最外面結構體的對應的重名屬性
stu.name = "whaha" //修改Student結構體類型的name屬性
stu.Person.name = "zs" //修改Person結構體類型的name屬性
stu.Person.Object.name = "lili" //修改Object結構體類型的name屬性
fmt.Println(stu) //{{{lili} zs 13} whaha 39.2}
-
第三種方式
type 結構體名稱1 struct{}
type 結構體名稱2 struct{
}
type 結構體名稱3 struct{
結構體名稱1
結構體名稱2
}
//第三種方式
//沒有重名屬性情況
type Object struct {
name string
}
type Person struct {
age int
}
type Student struct {
Object
Person
score float64
}
//定義變量同時初始化
stu := Student{Object{"lnj"},Person{19},30.6}
fmt.Println(stu) //{{lnj} {19} 30.6}
//操作結構體屬性
stu.Person.age = 30
stu.Object.name = "wjh"
fmt.Println(stu) //{{wjh} {30} 30.6}
//有重名屬性的情況
type Object struct {
name string
}
type Person struct {
name string
age int
}
type Student struct {
Object
Person
name string
score float64
}
stu := Student{Object{"haha"},Person{"lnj", 19},"wjh", 30.5}
fmt.Println(stu)
//操作結構體屬性
stu.name = "ll"
stu.Person.name = "zz"
stu.Object.name = "kk"
fmt.Println(stu)
結構體嵌套定義注意點
- 結構體的屬性類型不能是當前結構體的類型(不能自己嵌套自己)
- 只有匿名屬性才會向上查找, 非匿名屬性不會向上查找
package main
import "fmt"
func main() {
/*
1.結構體的嵌套定義的注意點:
1.1結構體的屬性類型不能是當前結構體的類型
1.2只有匿名屬性才會向上查找, 非匿名屬性不會向上查找
*/
type Person struct {
//Person 結構體屬性不能是自己本身的結構體類型
name string
age int
}
type Student struct {
//per Person //非匿名結構體屬性
Person //匿名結構體屬性
score float32
}
stu := Student{Person{"wjh", 18}, 52.3}
fmt.Println(stu)
//匿名結構體屬性會自動往匿名結構體查找屬性
//非匿名結構體屬性使用這種方法查找會報錯
fmt.Println(stu.name)
fmt.Println(stu.age)
}