张三 参考文章

结构体指针

你可以定义指向结构体的指针类似于其他指针变量,格式如下:

var struct_pointer *Books

以上定义的指针变量可以存储结构体变量的地址。查看结构体变量地址,可以将 & 符号放置于结构体变量前:

struct_pointer = &Book1;

使用结构体指针访问结构体成员,使用 . 操作符:

struct_pointer.title;

定义结构体:

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}

解释:

其实跟普通的指针是一样的,只不过这次是指定的结构体的指针,在上面的例子中:

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的值