Go 語言結構體
Go 語言中數組可以存儲同一類型的數據,但在結構體中我們可以為不同項定義不同的數據類型。
結構體是由一系列具有相同類型或不同類型的數據構成的數據集合。
結構體表示一項記錄,比如保存圖書館的書籍記錄,每本書有以下屬性:
Title :標題
Author : 作者
Subject:學科
ID:書籍ID
定義結構體
結構體定義需要使用 type 和 struct 語句。struct 語句定義一個新的數據類型,結構體有中有一個或多個成員。type 語句設定了結構體的名稱。
語法:
type struct_variable_type struct {
member definition;
member definition;
...
member definition;
}
//例子:
type Books struct {
title string
author string
subject string
book_id int
}
那么就可以使用如下的定義方式:
variable_name := structure_variable_type {value1, value2...valuen}
或
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
// 例子:
var book1 = Books {"Go 入門到放棄","yuantiankai","go系列教程",012231}
訪問結構體成員
如果要訪問結構體成員,需要使用點號 . 操作符,格式為:
結構體.成員名
//例子:
fmt.Println(book1.author)
fmt.Println(book1.title)
結構體作為函數參數
你可以像其他數據類型一樣將結構體類型作為參數傳遞給函數。並以以上實例的方式訪問結構體變量:
//例子:
func printBook( book Books ) {
fmt.Printf( "Book title : %s\n", book.title);
fmt.Printf( "Book author : %s\n", book.author);
fmt.Printf( "Book subject : %s\n", book.subject);
fmt.Printf( "Book book_id : %d\n", book.book_id);
}
然后這個printBook函數可以在主函數中調用。
結構體指針
你可以定義指向結構體的指針類似於其他指針變量,格式如下:
var struct_pointer *Books
以上定義的指針變量可以存儲結構體變量的地址。查看結構體變量地址,可以將 & 符號放置於結構體變量前:
struct_pointer = &Book1;
使用結構體指針訪問結構體成員,使用 "." 操作符:
struct_pointer.title;:
//例子:
var b *Books
b = &Book1
fmt.Println(b) //&{Go 語言 www.runoob.com Go 語言教程 6495407}
fmt.Println(*b) //{Go 語言 www.runoob.com Go 語言教程 6495407}
fmt.Println(&b) //0xc000082018
fmt.Println(Book1) //{Go 語言 www.runoob.com Go 語言教程 6495407}
//解釋:
其實跟普通的指針是一樣的,只不過這次是指定的結構體的指針,在上面的例子中:
var b *Books //就是說b這個指針是Books類型的。
b = &Book1 //Book1是Books的一個實例化的結構,&Book1就是把這個結構體的內存地址賦給了b,
*b //那么在使用的時候,只要在b的前面加個*號,就可以把b這個內存地址對應的值給取出來了
&b // 就是取了b這個指針的內存地址,也就是b這個指針是放在內存空間的什么地方的。
Book1 // 就是Book1這個結構體,打印出來就是它自己。也就是指針b前面帶了*號的效果。
//只有一個特殊的地方,盡管b所表示的是Book1對象的內存地址,但是,在從b對應的內存地址取屬性值的時候,就不是*b.title了。而是直接使用b.title,這點很特殊,它的效果就相當於Book1.title:
fmt.Println(b.title) //Go 入門到放棄
fmt.Println(Book1.title) //Go 入門到放棄
fmt.Println(b.author) //yuantiankai
fmt.Println(Book1.author) //yuantiankai
具體區別:
比如我們要寫一個函數修改結構體里的一個值,那么我們需要將修改過后的值返回出來,然后再重新賦值,比如這樣:
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func changeBook(book Books) string { //把book對象傳進來,返回的值是string類型的,也就是將被修改的值返回出來。
book.title = "book1_change"
return book.title
}
func main() {
var book1 Books;
book1.title = "book1"
book1.author = "zuozhe"
book1.book_id = 1
var res = changeBook(book1) //然后在外面拿到被修改的值
book1.title = res // 再重新賦值
fmt.Println(book1)
}
//結果為:
{book1_change zuozhe 1}
如果我們這樣做,是行不通的,看如下代碼:
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func changeBook(book Books) { //這個函數沒有返回值
book.title = "book1_change" //僅僅是修改了一下
}
func main() {
var book1 Books;
book1.title = "book1"
book1.author = "zuozhe"
book1.book_id = 1
changeBook(book1) //將book1傳進去,本意是想修改book1里面的值
fmt.Println(book1)
}
//結果為:
{book1 zuozhe 1} // 但是結果現實並沒有任何修改。
但是有了結構體指針,就不是值傳遞了,而是引用傳遞(傳遞的是地址)了。就可以這么寫了:
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func changeBook(book *Books) { // 這個方法傳入的參數一個Books類型的指針
book.title = "book1_change" //直接用指針.屬性的方式,修改原地址的值。
}
func main() {
var book1 Books;
book1.title = "book1"
book1.author = "zuozhe"
book1.book_id = 1
changeBook(&book1) //將book1這個對象的內存地址傳進去,
fmt.Println(book1)
}
//結果為:
{book1_change zuozhe 1} //成功修改了book1的值