Go - void 函数和直接赋值

mx8*_*x88 0 function void go assign

我在 Go 语言中遇到了一个小问题。我有这个结构:

type Time struct{
    hour,min,sec int
}
Run Code Online (Sandbox Code Playgroud)

以及初始化它的函数:

func init_Time(t Time) (int,int,int){
    t.hour, t.min, t.sec = time.Now().Clock()
    return t.hour, t.min, t.sec
}
Run Code Online (Sandbox Code Playgroud)

main

func main(){
   var Tm Time
   Tm.hour, Tm.min, Tm.sec = init_Time(Tm)
   fmt.Printf("Time: %d:%d:%d", Tm.hour, Tm.min, Tm.sec)
} 
Run Code Online (Sandbox Code Playgroud)

我也导入了time包。它工作得很好,但我有两个问题:

  1. 在我的代码中,为什么在函数中两次对变量(小时,分钟,秒)进行赋值init_Time

    t.小时、t.分钟、t.秒 = time.Now().Clock()

并在main()

Tm.hour, Tm.min, Tm.sec = init_Time(Tm)
Run Code Online (Sandbox Code Playgroud)

有必要还是我的错误?

  1. 为什么如果我init_Time通过将函数转换为 void 函数来修改该函数,它会返回值"Time: 0:0:0"而不是当前时间?

(例子:)

func init_Time(t Time) {
      t.hour, t.min, t.sec = time.Now().Clock()
}
...
func main(){
     var Tm Time
     init_Time(Tm)
     fmt.Printf("Time: %d:%d:%d", Tm.hour, Tm.min, Tm.sec)
} 
Run Code Online (Sandbox Code Playgroud)

icz*_*cza 5

调用任何函数(或方法)并传递值都会生成值的副本,并且在函数(或方法)内部您只能修改该副本。因此,如果您没有将第一个示例中的返回值分配给 的字段,则在函数返回时Time所做的更改将会丢失。init_Time()这也回答了你的第二个问题。

如果您希望调用者观察到更改,则必须传递一个指向您的值的指针,并让函数修改指向的值。在这种情况下,甚至不需要返回(修改后的)值:

func InitTime(t *Time) {
  t.hour, t.min, t.sec = time.Now().Clock()
}
Run Code Online (Sandbox Code Playgroud)

使用它:

t := Time{}
InitTime(&t)
fmt.Printf("Time: %d:%d:%d\n", t.hour, t.min, t.sec)
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上尝试):

Time: 23:0:0
Run Code Online (Sandbox Code Playgroud)

(请注意,Go Playground 上的当前时间始终从 23:00:00 开始。)

创建类似“构造函数”的函数也是惯用的:

func NewTime() *Time {
    t := &Time{}
    t.hour, t.min, t.sec = time.Now().Clock()
    return t
}
Run Code Online (Sandbox Code Playgroud)

使用它:

t2 := NewTime()
fmt.Printf("Time: %d:%d:%d\n", t2.hour, t2.min, t2.sec)
Run Code Online (Sandbox Code Playgroud)

输出是一样的。

查看相关问题:

Golang 运算符重载

当命名类型 T 的任何方法具有指针接收器时,复制类型 T 的实例