學(xué)海無涯苦作舟懦胞,書山有路勤為徑
寫在最前
最近出差剛回來瘟仿,想想在北京的日子真的是慘不忍睹,太熱了....而且對于我這個從小吃辣長大的川漢子來說研铆,簡直是折磨埋同。扯點閑談,現(xiàn)在進入正題吧蚜印。struct
又稱為機構(gòu)體,在c
語言或者是objective-c
留量、java
等其他語言中應(yīng)該是都有的窄赋,可以作為一個容器哟冬,裝入一些其他類型。在這之前忆绰,我也去重新復(fù)習(xí)了下c
和objective-c
中的結(jié)構(gòu)體浩峡。
struct回顧
下面就舉例說明下
幾種定義方式及其使用
//test1為結(jié)構(gòu)名 而 后面的test1Rename為結(jié)構(gòu)變量
typedef struct test1{
CGFloat a;
CGFloat b;
}test1Rename;
struct test2{
CGFloat c;
CGFloat d;
};
typedef struct test2 test2Rename;
typedef struct {
CGFloat a;
CGFloat b;
}test3Rename;
struct test4{
CGFloat a;
CGFloat b;
};
struct{
CGFloat a;
CGFloat b;
}test5Rename;
struct test6{
CGFloat a;
CGFloat b;
}test6Rename;
//typedef 的作用是為一種數(shù)據(jù)類型定義一個新名字
//使用
test1Rename test1rename = {9,9};
struct test1 test1 = {10,11};
test2Rename test2rename = {11,12};
struct test2 test2 = {21,22};
test3Rename test3rename = {1,2};
struct test4 test4 = {22,33};
test5Rename.a = 10;
test5Rename.b = 19;
test6Rename.a = 11;
test6Rename.b = 12;
struct test6 test6 ={12,23};
上面定義了六種方式的結(jié)構(gòu)體,其中前三種為帶typedef
關(guān)鍵字错敢,后面不帶翰灾,那么這個關(guān)鍵字又是什么意思呢?其大意就是為一種數(shù)據(jù)類型定義一個新名字
稚茅,下面我們就根據(jù)例子的使用情況來講解下纸淮。
-
1和2 兩種都是帶了
typedef
且定義的時候有結(jié)構(gòu)名和結(jié)構(gòu)變量名在使用結(jié)構(gòu)體的時候,我們可以有兩種不同的方式亚享,分別通過結(jié)構(gòu)名來創(chuàng)建新的變量和通過結(jié)構(gòu)變量來創(chuàng)建
唯一的區(qū)別在于 咽块,通過結(jié)構(gòu)名來創(chuàng)建,需要在前面加上
struct
欺税,而通過結(jié)構(gòu)變量來創(chuàng)建則少了struct
test1Rename test1rename = {9,9}; struct test1 test1 = {10,11}; test2Rename test2rename = {11,12}; struct test2 test2 = {21,22};
3沒有定義結(jié)構(gòu)名侈沪,而是直接通過
typedef
來創(chuàng)建了一個結(jié)構(gòu)變量,在使用的時候晚凿,同1和2中的通過結(jié)構(gòu)變量來使用是一樣的-
4亭罪、5、6均沒有使用
typedef
歼秽,4沒有定義結(jié)構(gòu)變量应役,所以在使用的時候必須加上struct
struct test4 test4 = {22,33};
5沒有定義結(jié)構(gòu)名,卻定義的有結(jié)構(gòu)變量哲银,但是這里我們不同通過結(jié)構(gòu)變量來創(chuàng)建結(jié)構(gòu)體扛吞,只能直接使用該結(jié)構(gòu)體變量,因為沒有通過
typedef
來定義test5Rename.a = 10; test5Rename.b = 19; //test5Rename test5rename = {1,2}; 錯誤
6則既定義了結(jié)構(gòu)名也定義了結(jié)構(gòu)變量荆责,其中的結(jié)構(gòu)變量可以直接使用滥比,結(jié)構(gòu)名可以用來創(chuàng)建新的結(jié)構(gòu)變量
test6Rename.a = 11; test6Rename.b = 12; struct test6 test6 ={12,23};
?
到這里,我們就差不多對結(jié)構(gòu)體有了大概的了解做院,對typedef
的作用也大概有了了解盲泛,下面就進入今天的主題,在go
中的struct
struct
在go
中键耕,其定義為
type structName struct {
var1 string
var2 int
}
可以看出寺滚,在go
中聲明一個struct
還是挺簡單的,那么怎么使用呢屈雄?看下面代碼
//定義一個Anima 結(jié)構(gòu)體
type Anima struct {
Name string
Age int
}
//使用方式
anima1 := hellotest.Anima{}
anima1.Age = 12
anima1.Name = "大象"
fmt.Println(anima1.Age,anima1.Name)
anima2 := hellotest.Anima{"河馬",14}
fmt.Println(anima2.Name,anima2.Age)
anima3 := hellotest.Anima{Age:9,Name:"豹子"}
fmt.Println(anima3.Age,anima3.Name)
var anima4 hellotest.Anima
anima4.Age = 14
anima4.Name = "獅子"
在上面的使用方式中村视,有一種需要特別注意,那就是anima2 := hellotest.Anima{"河馬",14}
這種方式酒奶,必須按照順序提供初始化值蚁孔,及按照我們定義的結(jié)構(gòu)體中的屬性的順序來賦值
注:由于上面奶赔,我是在package
hellotest
中定義的結(jié)構(gòu)體,所以在main
package
中使用的時候杠氢,加了hellotest.
的方式來調(diào)用站刑,這中需要注意的是,結(jié)構(gòu)體如果要被其他的包引用鼻百,那么結(jié)構(gòu)體的首字母必須大寫绞旅,而且里面屬性如果需要被用到,也必須大寫温艇。
struct匿名字段
在go
語言中因悲,定義struct
的時候,除了類型和字段名一一對應(yīng)中贝,也可以支持不寫字段名囤捻,而只寫類型,也就是匿名字段邻寿。
下面看看例子
//匿名字段
type Cat struct {
int
string
}
func CatInfo() {
cat := Cat{12,"小花"}
fmt.Println(cat.string,cat.int);
}
//調(diào)用CatInfo方法
hellotest.CatInfo()
//輸出結(jié)果
小花 12
上面的例子中匿名字段的類型蝎土,都是一些基本類型,如果換成是struct
又會怎么樣呢绣否?我們就已剛剛那個Cat
為例子誊涯,在其中加入Anima
//匿名字段
type Cat struct {
Anima
int
string
}
func CatInfo() {
cat := Cat{Anima{"動物類型",4},12,"小花"}
fmt.Println(cat.Age,cat.Name,cat.string,cat.int);
cat.Age = 5;
cat.Name = "動物類型-溫順動物"
fmt.Println(cat.Age,cat.Name,cat.string,cat.int);
cat.Anima.Age = 6;
cat.Anima.Name = "動物類型-溫順動物-貓科"
fmt.Println(cat.Age,cat.Name,cat.string,cat.int);
cat.Anima = Anima{"動物類型-溫順動物-貓科-白貓",7}
fmt.Println(cat.Age,cat.Name,cat.string,cat.int);
}
//輸出結(jié)果為
4 動物類型 小花 12
5 動物類型-溫順動物 小花 12
6 動物類型-溫順動物-貓科 小花 12
7 動物類型-溫順動物-貓科-白貓 小花 12
通過上面的例子 我們可以看到,當(dāng)匿名字段是struct
的時候蒜撮,struct
的全部字段都被隱式的加入了當(dāng)前的結(jié)構(gòu)體中暴构,我們不僅可以直接通過當(dāng)前的結(jié)構(gòu)體來調(diào)用,也可以訪問匿名字段類型作為字段名段磨,而且可以在相應(yīng)的字段上面進行函數(shù)操作取逾,如上面的
cat.Anima.Age = 6;
cat.Anima.Name = "動物類型-溫順動物-貓科"
fmt.Println(cat.Age,cat.Name,cat.string,cat.int);
cat.Anima = Anima{"動物類型-溫順動物-貓科-白貓",7}
fmt.Println(cat.Age,cat.Name,cat.string,cat.int);
但是值得注意的是,初始化的時候苹支,必須通過匿名的struct
來砾隅,但是后面改變值的時候,可以直接修改债蜜,如下面的方式是不可行的
cat1 := Cat{"動物類型",4,12,"小花"}
fmt.Println(cat.Age,cat.Name,cat.string,cat.int);
最后還有一個問題晴埂,那就是如果我們的匿名struct
中有個字段和我們的當(dāng)前struct
中都有相同的字段,那該怎么辦呢寻定?
在go
語言中儒洛,所采取的方式是優(yōu)先采用最外層的屬性,并且里層的需要訪問狼速,就必須通過匿名字段作為字段名來訪問琅锻。看下面例子
type Anima struct {
Name string
Age int
}
type Dog struct {
Anima
Sex string
Name string
}
func DogInfo() {
dog := Dog{Anima{"動物類型",8},"公的","動物類型-兇猛動物-狗"}
fmt.Println(dog.Anima.Name,dog.Age,dog.Name,dog.Sex)
dog.Name = "動物類型-兇猛動物-狗-小白狗"
fmt.Println(dog.Anima.Name,dog.Name)
}
//輸出結(jié)果
動物類型 8 動物類型-兇猛動物-狗 公的
動物類型 動物類型-兇猛動物-狗-小白狗
從上面的例子中,可以看出恼蓬,訪問順序的優(yōu)先級