Golang这段代码是什么意思?

Golang这段代码是什么意思? 请参考此链接:https://go.dev/play/p/mPYw900P1vT

第11-13行。向结构体传递一个“指针”并返回结构体的“地址”是什么意思?

我的理解是 “&” 会返回实体的地址。当我们想要的是实际的实体时,为什么要返回地址呢?

所以我有两个问题:

  1. 返回一个指向 MyStruct 的指针是什么意思?
  2. 当我们想要实际的值时,为什么要返回结构体的地址?

我是新手,这让我很困惑,因为我在所有代码中都看到这种模式。尤其是在使用像 net/http 这样的第三方库时。


更多关于Golang这段代码是什么意思?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复
  1. 返回一个指向结构体的指针意味着该结构体不会被复制。

Go 有两种向函数传递数据和从函数返回数据的模式:

  • 按值传递。在这种情况下,数据在传递给函数或从函数返回时会被复制。如果接收方操作接收到的副本,原始数据保持不变。
  • 按引用传递。在这种情况下,只有指向数据的指针被传递给函数或从函数返回。如果接收方操作数据,它操作的是原始数据。

这里有一个视频 直观地展示了指针的本质。(提示:请务必观看视频,而不仅仅是阅读视频下方的文字。该文字只是视频的转录稿。视频提供了超越文字表达能力的视觉解释。)

更多关于Golang这段代码是什么意思?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这是一个关于Go语言中指针和值语义的重要问题。让我解释一下第11-13行的代码:

func NewMyStruct() *MyStruct {
    return &MyStruct{}
}

1. 返回指向MyStruct的指针是什么意思?

这意味着函数返回的是结构体在内存中的地址,而不是结构体的副本。在Go中:

// 返回指针 - 调用者得到的是内存地址
func NewMyStruct() *MyStruct {
    return &MyStruct{}  // 创建结构体并返回其地址
}

// 返回值 - 调用者得到的是副本
func NewMyStructValue() MyStruct {
    return MyStruct{}  // 创建结构体并返回其副本
}

2. 为什么返回结构体地址而不是实际值?

主要有以下几个原因:

a) 避免复制开销

对于大型结构体,复制整个结构体比复制一个指针(通常是8字节)代价更高:

type LargeStruct struct {
    data [1000]int
}

// 低效 - 复制1000个整数
func ReturnValue() LargeStruct {
    return LargeStruct{}
}

// 高效 - 只复制指针
func ReturnPointer() *LargeStruct {
    return &LargeStruct{}
}

b) 允许修改原始数据

当调用者需要修改结构体时,指针确保所有代码都引用同一个实例:

type Counter struct {
    value int
}

func NewCounter() *Counter {
    return &Counter{value: 0}
}

func (c *Counter) Increment() {
    c.value++  // 修改原始结构体
}

func main() {
    counter := NewCounter()
    counter.Increment()  // 所有修改都作用于同一个实例
    fmt.Println(counter.value)  // 输出: 1
}

c) 支持nil值

指针可以表示"无值"状态:

func FindUser(id int) *User {
    if id <= 0 {
        return nil  // 指针可以返回nil
    }
    return &User{ID: id}
}

d) 一致性(特别是在net/http中)

许多标准库和第三方库使用这种模式保持一致性:

// net/http的典型用法
func handler(w http.ResponseWriter, r *http.Request) {
    // r 是指向http.Request的指针
    // w 是接口,但底层通常包含指针
}

// 创建服务器
server := &http.Server{
    Addr:    ":8080",
    Handler: handler,
}

实际示例对比

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

// 返回指针
func NewPersonPointer(name string, age int) *Person {
    return &Person{Name: name, Age: age}
}

// 返回值
func NewPersonValue(name string, age int) Person {
    return Person{Name: name, Age: age}
}

func main() {
    // 使用指针
    p1 := NewPersonPointer("Alice", 30)
    p1.Age = 31  // 直接修改原始数据
    
    // 使用值
    p2 := NewPersonValue("Bob", 25)
    p2.Age = 26  // 这只是修改副本
    
    fmt.Printf("指针: %v, 值: %v\n", p1.Age, p2.Age)
}

在Go中,返回结构体指针是常见模式,因为它提供了更好的性能、允许修改原始数据,并且与许多标准库API保持一致。对于小型结构体或不需要修改的情况,返回值也是可以的,但指针方式更为普遍。

回到顶部