Go 语言结构体
Go 语言中数组可以存储同一类型的数据,但在结构体中我们可以为不同项定义不同的数据类型。
结构体是由一系列具有相同类型或不同类型的数据构成的数据集合。
结构体表示一项记录,比如保存图书馆的书籍记录,每本书有以下属性:
- Title :标题
- Author : 作者
- Subject:学科
- ID:书籍ID
定义结构体
结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。结构体的格式如下:
type struct_variable_type struct {
member definition
member definition
...
member definition
}
一旦定义了结构体类型,它就能用于变量的声明,语法格式如下:
variable_name := structure_variable_type {value1, value2...valuen}
或
variable_name := structure_variable_type { key1: value1, key2: value2..., keyn: valuen}
实例如下:
实例
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})
}
输出结果为:
{Go 语言 www.runoob.com Go 语言教程 6495407}
{Go 语言 www.runoob.com Go 语言教程 6495407}
{Go 语言 www.runoob.com 0}
访问结构体成员
如果要访问结构体成员,需要使用点号 . 操作符,格式为:
结构体.成员名"
结构体类型变量使用 struct 关键字定义,实例如下:
实例
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
var Book2 Books /* 声明 Book2 为 Books 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 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 book_id : %d\n", Book1.book_id)
/* 打印 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 book_id : %d\n", Book2.book_id)
}
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
var Book2 Books /* 声明 Book2 为 Books 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 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 book_id : %d\n", Book1.book_id)
/* 打印 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 book_id : %d\n", Book2.book_id)
}
以上实例执行运行结果为:
Book 1 title : Go 语言 Book 1 author : www.runoob.com Book 1 subject : Go 语言教程 Book 1 book_id : 6495407 Book 2 title : Python 教程 Book 2 author : www.runoob.com Book 2 subject : Python 语言教程 Book 2 book_id : 6495700
结构体作为函数参数
你可以像其他数据类型一样将结构体类型作为参数传递给函数。并以以上实例的方式访问结构体变量:
实例
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
var Book2 Books /* 声明 Book2 为 Books 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6495700
/* 打印 Book1 信息 */
printBook(Book1)
/* 打印 Book2 信息 */
printBook(Book2)
}
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)
}
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
var Book2 Books /* 声明 Book2 为 Books 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6495700
/* 打印 Book1 信息 */
printBook(Book1)
/* 打印 Book2 信息 */
printBook(Book2)
}
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)
}
以上实例执行运行结果为:
Book title : Go 语言 Book author : www.runoob.com Book subject : Go 语言教程 Book book_id : 6495407 Book title : Python 教程 Book author : www.runoob.com Book subject : Python 语言教程 Book book_id : 6495700
结构体指针
你可以定义指向结构体的指针类似于其他指针变量,格式如下:
var struct_pointer *Books
以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前:
struct_pointer = &Book1
使用结构体指针访问结构体成员,使用 "." 操作符:
struct_pointer.title
接下来让我们使用结构体指针重写以上实例,代码如下:
实例
package main
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
var Book2 Books /* 声明 Book2 为 Books 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6495700
/* 打印 Book1 信息 */
printBook(&Book1)
/* 打印 Book2 信息 */
printBook(&Book2)
}
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)
}
import "fmt"
type Books struct {
title string
author string
subject string
book_id int
}
func main() {
var Book1 Books /* 声明 Book1 为 Books 类型 */
var Book2 Books /* 声明 Book2 为 Books 类型 */
/* book 1 描述 */
Book1.title = "Go 语言"
Book1.author = "www.runoob.com"
Book1.subject = "Go 语言教程"
Book1.book_id = 6495407
/* book 2 描述 */
Book2.title = "Python 教程"
Book2.author = "www.runoob.com"
Book2.subject = "Python 语言教程"
Book2.book_id = 6495700
/* 打印 Book1 信息 */
printBook(&Book1)
/* 打印 Book2 信息 */
printBook(&Book2)
}
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)
}
以上实例执行运行结果为:
Book title : Go 语言 Book author : www.runoob.com Book subject : Go 语言教程 Book book_id : 6495407 Book title : Python 教程 Book author : www.runoob.com Book subject : Python 语言教程 Book book_id : 6495700
星海
yan***anbao12@163.com
结构体是作为参数的值传递:
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) 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) { book.title = "book1_change" } func main() { var book1 Books book1.title = "book1" book1.author = "zuozhe" book1.book_id = 1 changeBook(&book1) fmt.Println(book1) }结果为:
{book1_change zuozhe 1}星海
yan***anbao12@163.com
Ng Li
ngl***163.com
struct 类似于 java 中的类,可以在 struct 中定义成员变量。
要访问成员变量,可以有两种方式:
不需要通过 getter, setter 来设置访问权限。
type Rect struct{ //定义矩形类 x,y float64 //类型只包含属性,并没有方法 width,height float64 } func (r *Rect) Area() float64{ //为Rect类型绑定Area的方法,*Rect为指针引用可以修改传入参数的值 return r.width*r.height //方法归属于类型,不归属于具体的对象,声明该类型的对象即可调用该类型的方法 }Ng Li
ngl***163.com
MissLi
luy***.w@yahoo.com
参考地址
利用指针改变结构体对应的值:
package main import ( "fmt" "strconv" ) type Books struct { title string author string subject string book_id int } 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 id: %d\n", book.book_id) } func changeBook(book *Books, new_info_type string, new_info string) { if new_info_type == "title" { book.title = new_info } else { if new_info_type == "author" { book.author = new_info } else { if new_info_type == "subject" { book.subject = new_info } else { int, err := strconv.Atoi(new_info) if err == nil { book.book_id = int } } } } } func main() { book1 := Books{"Go Language", "www.golang.com", "Go语言基础", 6495407} book2 := Books{"Harry Porter", "www.youku.com", "Deathly Hallows", 6448722} fmt.Println("------原始信息------") printBook(book1) printBook(book2) fmt.Println("------新的信息-------") changeBook(&book1, "title", "Summer") changeBook(&book2, "book_id", "1111111") printBook(book1) printBook(book2) }MissLi
luy***.w@yahoo.com
参考地址
灭霸
143***7200@qq.com
结构体中属性的首字母大小写问题
注意: 这个 public 和 private 是相对于包(go 文件首行的 package 后面跟的包名)来说的。
敲黑板,划重点
当要将结构体对象转换为 JSON 时,对象中的属性首字母必须是大写,才能正常转换为 JSON。
示例一:
type Person struct { Name string //Name字段首字母大写 age int //age字段首字母小写 } func main() { person:=Person{"小明",18} if result,err:=json.Marshal(&person);err==nil{ //json.Marshal 将对象转换为json字符串 fmt.Println(string(result)) } }控制台输出:
{"Name":"小明"} //只有Name,没有age示例二:
type Person struct{ Name string //都是大写 Age int }控制台输出:
{"Name":"小明","Age":18} //两个字段都有那这样 JSON 字符串以后就只能是大写了么? 当然不是,可以使用 tag 标记要返回的字段名。
示例三:
type Person struct{ Name string `json:"name"` //标记json名字为name Age int `json:"age"` Time int64 `json:"-"` // 标记忽略该字段 } func main(){ person:=Person{"小明",18, time.Now().Unix()} if result,err:=json.Marshal(&person);err==nil{ fmt.Println(string(result)) } }控制台输出:
{"name":"小明","age":18}灭霸
143***7200@qq.com
森林里的小动物
wuk***67@gmail.com
使用结构体的时候需要注意的点:定义的结构体如果只在当前包内使用,结构体的属性不用区分大小写。如果想要被其他的包引用,那么结构体的属性的首字母需要大写。例如
package mode //结构体小写开头的属性只能包内调用 type Books struct { Title string Author string Subject string book_id int }当该结构体被引用时:
import ( "fmt" "src/mode" ) func main() { var Book1 mode.Books /* 声明 Book1 为 Books 类型 */ /* book 1 描述 */ Book1.Title = "Go 语言" Book1.Author = "www.runoob.com" Book1.Subject = "Go 语言教程" // 如果进行了如下调用,则会报错 // Book1.book_id = 6495407 /* 打印 Book1 信息 */ printBook(Book1) } 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) }森林里的小动物
wuk***67@gmail.com
张三
461***35@qq.com
参考地址
结构体指针
你可以定义指向结构体的指针类似于其他指针变量,格式如下:
以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前:
使用结构体指针访问结构体成员,使用 . 操作符:
定义结构体:
type Books struct { title string author string subject string book_id int } var book1 = Books {"Go 入门到放弃","yuantiankai","go系列教程",012231}例子:
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}解释:
其实跟普通的指针是一样的,只不过这次是指定的结构体的指针,在上面的例子中:
只有一个特殊的地方,尽管 b 所表示的是 Book1 对象的内存地址,但是,在从 b 对应的内存地址取属性值的时候,就不是 *b.title 了。而是直接使用b.title,这点很特殊,它的效果就相当于 Book1.title:
具体区别:
比如我们要写一个函数修改结构体里的一个值,那么我们需要将修改过后的值返回出来,然后再重新赋值,比如这样:
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的值张三
461***35@qq.com
参考地址
冰河
ofy***@qq.com
一文讲清GO语言结构体指针
学GO语言第三天,分享自己边学边写的学习笔记。首发至菜鸟评论区,禁止任何形式的转载!
我是小洋,祝你幸福。
/* GO语言结构体指针 1. 没有特别,与一般指针一致。 2. 调用成员变量可以使用 变量名.成员名、指针名.成员名 都可以,相当于自动解引用,不需要c语言的 -> 符号。 3. GO语言的自动解引用只支持到一级指针,多级指针就要至少手动解引用至一级指针。看来GO是做了,但是没完全做。 */ package main import "fmt" func t02_test1() { // Books 在包内定义过,可以直接使用 var book Books book.title = "Go 语言" book.author = "www.runoob.com" book.subject = "Go 语言教程" book.book_id = 6495407 printBook(book) printBookByPoniter(&book) // GO语言不支持形如 &&book 这样直接构造多级地址,需要使用变量来构造 p1 := &book p2 := &p1 printBookByPoniter2(p2) } func printBook(book Books) { // 传参的本质是为局部变量赋值,此book为本函数的局部变量,和外部的book是两个独立的变量。 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) } func printBookByPoniter(book *Books) { // 仍然遵循传参的本质是为局部变量赋值。此book的值是外部book的内存地址,可以由此间接操作外部变量。不能说是将外部变量传递了进来,模糊化复杂化的概念不可取。 // 在GO语言中,可以直接使用 指针.成员名 ,无需像C语言那样解引用。类似Rust的自动解引用。 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) } func printBookByPoniter2(book **Books) { // GO语言的自动解引用只支持到一级指针,多级指针就要至少手动解引用至一级指针,否则报错。看来GO是做了,但是没完全做。 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) }冰河
ofy***@qq.com