原文鏈接:http://oldchen.iwulai.com/index.php/2019/01/15/go%E5%9F%BA%E7%A1%80%E7%BC%96%E7%A8%8B%EF%BC%9A%E7%BB%93%E6%9E%84%E4%BD%93%EF%BC%88struct%EF%BC%89/
結構體(struct)是用戶自定義的類型,它代表若干字段的集合。有些時候將多個數據看做一個整體要比單獨使用這些數據更有意義,這種情況下就適合使用結構體。
1.結構體的聲明
type person struct {//聲明一個名爲 person 的結構體類型
name string//一個string類型的字段name,用來保存用戶名稱這個屬性
addr string//一個string類型的字段addr,用來保存用戶地址這個屬性
age int//一個int類型的字段age,用來保存用戶年齡這個屬性
}
Go語言中,也和C或者其他語言一樣,我們可以聲明新的類型,作爲其它類型的屬性或字段的容器。例如,我們可以創建一個自定義類型person代表一個人的實體。這個實體擁有屬性:姓名和年齡。這樣的類型我們稱之struct。
等價於:
type person struct {//聲明一個名爲 person 的結構體類型
name, addr string
age int
}
我們也可以定義一個沒有類型名稱的結構體,這種結構體叫做匿名結構體(anonymous structures)。
var person struct {//聲明一個名爲 person 的結構體類型
name, addr string
age int
}
//定義匿名結構體時沒有 type 關鍵字,與其他定義類型的變量一樣,如果在函數外部
//需在結構體變量前加上 var 關鍵字,在函數內部可省略 var 關鍵字。
2 結構體初始化
2.1 普通變量
package main
import "fmt"
type Student struct {
id int
name string
sex byte
age int
addr string
}
func main() {
//1、順序初始化,必須每個成員都初始化
var s1 Student = Student{1, "mike", 'm', 18, "sz"}
s2 := Student{2, "yoyo", 'f', 20, "sz"}
//s3 := Student{2, "tom", 'm', 20} //err, too few values in struct initializer
//2、指定初始化某個成員,沒有初始化的成員爲零值
s4 := Student{id: 2, name: "lily"}
fmt.Println(s1,s2,s4)
// {1 mike 109 18 sz} {2 yoyo 102 20 sz} {2 lily 0 0 }
}
2.2 指針變量
package main
import "fmt"
type Student struct {
id int
name string
sex byte
age int
addr string
}
func main() {
var s5 *Student = &Student{3, "xiaoming", 'm', 16, "bj"}
s6 := &Student{4, "rocco", 'm', 3, "sh"}
fmt.Println(s5,s6)//&{3 xiaoming 109 16 bj} &{4 rocco 109 3 sh}
}
3 .結構體成員的使用
3.1 普通變量
package main
import "fmt"
type Student struct {
id int
name string
sex byte
age int
addr string
}
func main() {
//===============結構體變量爲普通變量
//1、打印成員
var s1 = Student{1, "mike", 'm', 18, "sz"}
//結果:id = 1, name = mike, sex = m, age = 18, addr = sz
fmt.Printf("id = %d, name = %s, sex = %c, age = %d, addr = %s\n", s1.id, s1.name, s1.sex, s1.age, s1.addr)
//2、成員變量賦值
var s2 Student
s2.id = 2
s2.name = "yoyo"
s2.sex = 'f'
s2.age = 16
s2.addr = "guangzhou"
fmt.Println(s2) //{2 yoyo 102 16 guangzhou}
}
3.2 指針變量
package main
import "fmt"
type Student struct {
id int
name string
sex byte
age int
addr string
}
func main() {
//===============結構體變量爲指針變量
//3、先分配空間,再賦值
s3 := new(Student)
s3.id = 3
s3.name = "xxx"
fmt.Println(s3) //&{3 xxx 0 0 }
//4、普通變量和指針變量類型打印
var s4 Student = Student{4, "yyy", 'm', 18, "sz"}
fmt.Printf("s4 = %v, &s4 = %v\n", s4, &s4) //s4 = {4 yyy 109 18 sz}, &s4 = &{4 yyy 109 18 sz}
var p *Student = &s4
//p.成員 和(*p).成員 操作是等價的
p.id = 5
(*p).name = "zzz"
fmt.Println(p, *p, s4) //&{5 zzz 109 18 sz} {5 zzz 109 18 sz} {5 zzz 109 18 sz}
}
4 .結構體比較
如果結構體的全部成員都是可以比較的,那麼結構體也是可以比較的,那樣的話兩個結構體將可以使用 == 或 != 運算符進行比較,但不支持 > 或 < 。
package main
import "fmt"
type Student struct {
id int
name string
sex byte
age int
addr string
}
func main() {
s1 := Student{1, "mike", 'm', 18, "sz"}
s2 := Student{1, "mike", 'm', 18, "sz"}
fmt.Println("s1 == s2", s1 == s2) //s1 == s2 true
fmt.Println("s1 != s2", s1 != s2) //s1 != s2 false
}
5 結構體作爲函數參數
5.1 值傳遞
package main
import "fmt"
type Student struct {
id int
name string
sex byte
age int
addr string
}
func printStudentValue(tmp Student) {
tmp.id = 250
//printStudentValue tmp = {250 mike 109 18 sz}
fmt.Println("printStudentValue tmp = ", tmp)
}
func main() {
var s Student = Student{1, "mike", 'm', 18, "sz"}
printStudentValue(s)//值傳遞,形參的修改不會影響到實參
fmt.Println("main s = ", s) //main s = {1 mike 109 18 sz}
}
5.2 引用傳遞
package main
import "fmt"
type Student struct {
id int
name string
sex byte
age int
addr string
}
func printStudentPointer(p *Student) {
p.id = 250
//printStudentPointer p = &{250 mike 109 18 sz}
fmt.Println("printStudentPointer p = ", p)
}
func main() {
var s Student = Student{1, "mike", 'm', 18, "sz"}
printStudentPointer(&s)//引用(地址)傳遞,形參的修改會影響到實參
fmt.Println("main s = ", s)//main s = {250 mike 109 18 sz}
}
6. 可見性
Go語言對關鍵字的增加非常吝嗇,其中沒有private、 protected、 public這樣的關鍵字。
要使某個符號對其他包(package)可見(即可以訪問),需要將該符號定義爲以大寫字母 開頭。
目錄結構:
test.go示例代碼如下:
//test.go
package test
//student01只能在本文件件引用,因爲首字母小寫
type student01 struct {
Id int
Name string
}
//Student02可以在任意文件引用,因爲首字母大寫
type Student02 struct {
Id int
name string
}
main.go示例代碼如下:
// main.go
package main
import (
"fmt"
"test" //導入test包
)
func main() {
//s1 := test.student01{1, "mike"} //err, cannot refer to unexported name test.student01
//err, implicit assignment of unexported field 'name' in test.Student02 literal
//s2 := test.Student02{2, "yoyo"}
//fmt.Println(s2)
var s3 test.Student02 //聲明變量
s3.Id = 1 //ok
//s3.name = "mike" //err, s3.name undefined (cannot refer to unexported field or method name)
fmt.Println(s3)
}