Go 结构体
Go - 结构体 (Structs)
Section titled “Go - 结构体 (Structs)”虽然 Go 中的数组(arrays)和切片(slices)存放的是同一种类型的元素,但**结构体(structs)**是用户定义的类型,允许你将可能不同类型的相关数据项组合成一个单一的单元。
结构体对于建模现实世界中的实体或记录非常有用。例如,如果你想表示一本书的信息,你可以将书名(title)、作者(author)、主题(subject)和 ID 等属性组合在一起:
- 书名 (string)
- 作者 (string)
- 主题 (string)
- 图书ID (int)
你使用 type 和 struct 关键字来定义结构体。type 关键字引入一个新的类型名称,而 struct 则指定这个类型由一系列命名字段组成,每个字段都有自己的类型。
// 定义一个新的结构体类型 'Book'type Book struct { Title string // 字段 'Title',类型为 string Author string // 字段 'Author',类型为 string Subject string // 字段 'Subject',类型为 string BookID int // 字段 'BookID',类型为 int}定义之后,Book 就成为一个新的类型。你可以声明该类型的变量。
创建结构体实例(变量)
Section titled “创建结构体实例(变量)”有几种方法可以创建结构体类型的实例(变量):
// 1. 使用 'var' 关键字(字段获得零值)var book1 Book // book1.Title="",book1.Author="",...,book1.BookID=0
// 2. 使用短变量声明和结构体字面量(推荐)book2 := Book{ Title: "Go Programming", Author: "TutorialsPoint", Subject: "Go Programming Tutorial", BookID: 6495407,}
// 3. 不带字段名的结构体字面量(顺序必须与定义匹配 - 可读性差,应避免)book3 := Book{"Telecom Billing", "Zara Ali", "Telecom Billing Tutorial", 6495700}
// 4. 使用内置函数 'new'(返回指向零值结构体的指针)bookPtr := new(Book) // bookPtr 的类型是 *Book,指向一个零值的 Book 结构体访问结构体字段
Section titled “访问结构体字段”你使用点号(.)运算符来访问结构体实例的字段(成员)。
package main
import "fmt"
type Book struct { Title string Author string Subject string BookID int}
func main() { // 使用结构体字面量创建实例 book1 := Book{ Title: "Go Programming", Author: "TutorialsPoint", Subject: "Go Programming Tutorial", BookID: 6495407, } book2 := Book{"Telecom Billing", "Zara Ali", "Telecom Billing Tutorial", 6495700}
// 访问并打印 Book1 字段 fmt.Printf("Book 1 Title: %s\n", book1.Title) fmt.Printf("Book 1 Author: %s\n", book1.Author) fmt.Printf("Book 1 Subject: %s\n", book1.Subject) fmt.Printf("Book 1 BookID: %d\n", book1.BookID)
fmt.Println("---")
// 访问并打印 Book2 字段 fmt.Printf("Book 2 Title: %s\n", book2.Title) fmt.Printf("Book 2 Author: %s\n", book2.Author) fmt.Printf("Book 2 Subject: %s\n", book2.Subject) fmt.Printf("Book 2 BookID: %d\n", book2.BookID)
// 修改字段 book1.Author = "Updated Author" fmt.Printf("\nBook 1 Updated Author: %s\n", book1.Author)}输出:
Book 1 Title: Go ProgrammingBook 1 Author: TutorialsPointBook 1 Subject: Go Programming TutorialBook 1 BookID: 6495407---Book 2 Title: Telecom BillingBook 2 Author: Zara AliBook 2 Subject: Telecom Billing TutorialBook 2 BookID: 6495700
Book 1 Updated Author: Updated Author结构体作为函数参数
Section titled “结构体作为函数参数”你可以像传递其他任何类型一样将结构体传递给函数。默认情况下,Go 按值传递参数,这意味着函数接收的是结构体的副本。函数内部的修改不会影响原始结构体。
package main
import "fmt"
type Book struct { Title string Author string Subject string BookID int}
// 函数接受一个 Book 结构体(按值传递 - 接收副本)func printBookInfo(b Book) { fmt.Printf("Title: %s, Author: %s, ID: %d\n", b.Title, b.Author, b.BookID) // 在这里修改 'b' 只会改变副本 b.Title = "Changed inside function"}
func main() { book1 := Book{ Title: "Go Programming", Author: "TutorialsPoint", Subject: "Go Programming Tutorial", BookID: 6495407, }
fmt.Println("Printing Book 1:") printBookInfo(book1) // 传递 book1 的副本
fmt.Printf("Original Book 1 Title after function call: %s\n", book1.Title)}输出:
Printing Book 1:Title: Go Programming, Author: TutorialsPoint, ID: 6495407Original Book 1 Title after function call: Go Programming如果你需要一个函数来修改原始结构体,或者出于性能原因想避免复制大型结构体,你应该传递结构体的指针(pointer)。
你可以使用 *TypeName(例如 *Book)声明一个指向结构体的指针。使用 & 运算符获取结构体实例的地址。
var bookPtr *Book // 声明一个指向 Book 的指针book1 := Book{ ... }bookPtr = &book1 // 将 book1 的地址赋给 bookPtrGo 提供了一种方便的简写:你可以使用与结构体值相同的点号(.)表示法通过指针访问结构体的字段。Go 会自动为你解引用(dereference)指针。
// 你可以直接写成 bookPtr.Title,而不是 (*bookPtr).Title使用指针的示例:
package main
import "fmt"
type Book struct { Title string Author string Subject string BookID int}
// 函数接受一个指向 Book 的指针(*Book)func updateBookTitle(b *Book, newTitle string) { if b == nil { // 检查 nil 指针是一个好习惯 fmt.Println("Cannot update a nil book pointer") return } // 通过指针修改原始结构体的 Title 字段 b.Title = newTitle // Go 会自动处理 (*b).Title}
func main() { book1 := Book{ Title: "Go Programming", Author: "TutorialsPoint", Subject: "Go Programming Tutorial", BookID: 6495407, }
fmt.Printf("Original Title: %s\n", book1.Title)
// 将 book1 的地址 (&) 传递给函数 updateBookTitle(&book1, "Learning Go Structs")
fmt.Printf("Updated Title: %s\n", book1.Title)
// new() 的示例 bookPtr := new(Book) // 创建一个零值 Book 并返回一个 *Book 指针 updateBookTitle(bookPtr, "Pointer Example") fmt.Printf("Title from new() pointer: %s\n", bookPtr.Title)}输出:
Original Title: Go ProgrammingUpdated Title: Learning Go StructsTitle from new() pointer: Pointer Example