Go – void function and direct assignment

huangapple go评论154阅读模式
英文:

Go - void function and direct assignment

问题

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

type Time struct{
    hour,min,sec int
}

还有一个用于初始化的函数:

func init_Time(t Time) (int,int,int){
    t.hour, t.min, t.sec = time.Now().Clock()
    return t.hour, t.min, t.sec
}

然后是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)
} 

我也导入了time包。它完美地工作,但是我有两个问题:

  1. 在我的代码中,为什么在init_Time函数中变量(hour,min,sec)的赋值被执行了两次:

    t.hour, t.min, t.sec = time.Now().Clock()

以及在main()函数中:

Tm.hour, Tm.min, Tm.sec = init_Time(Tm)

这是必要的还是我的错误?

  1. 为什么如果我将init_Time函数修改为无返回值的函数,它会返回"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)
}
英文:

I have a little problem in Go language.
I have this struct:

type Time struct{
    hour,min,sec int
}

And this function that initializes it:

func init_Time(t Time) (int,int,int){
    t.hour, t.min, t.sec = time.Now().Clock()
    return t.hour, t.min, t.sec
}

And the main is:

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)
} 

I have imported time package too. It works perfectly but I have 2 questions about it:

  1. In my code, why is the assignment to the variables (hour,min,sec) twice done both in the init_Time function:

    t.hour, t.min, t.sec = time.Now().Clock()

and in the main():

Tm.hour, Tm.min, Tm.sec = init_Time(Tm)

Is it necessary or is my mistake?

  1. Why if I modify the init_Time function by transforming it into a void function, it returns values "Time: 0:0:0" instead of the current time?

(Example:)

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)
} 

答案1

得分: 5

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

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

func InitTime(t *Time) {
  t.hour, t.min, t.sec = time.Now().Clock()
}

使用它:

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

输出结果(在Go Playground上尝试):

Time: 23:0:0

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

此外,创建一个类似于“构造函数”的函数是惯用的做法:

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

使用它:

t2 := NewTime()
fmt.Printf("Time: %d:%d:%d\n", t2.hour, t2.min, t2.sec)

输出结果相同。

参考相关问题:

https://stackoverflow.com/questions/33040495/golang-operator-overloading/33040529#33040529

https://stackoverflow.com/questions/41477624/copy-instances-of-type-t-when-any-of-the-methods-of-a-named-type-t-have-a-point/41482152#41482152

英文:

Calling any function (or method) and passing values makes a copy of the values, and inside the function (or method) you can only modify the copy. Hence if you don't assign the return values in your first example to the fields of Time, changes made in init_Time() are lost when the function returns. This also answers your 2nd question.

If you want the caller to observe the changes, you must pass a pointer to your value, and have the function modify the pointed value. In this case it is not even required to return the (modified) value:

func InitTime(t *Time) {
  t.hour, t.min, t.sec = time.Now().Clock()
}

Using it:

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

Output (try it on the Go Playground):

Time: 23:0:0

(Note that the current time on the Go Playground always starts at 23:00:00.)

Also it's idiomatic to create a "constructor" like function:

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

Using it:

t2 := NewTime()
fmt.Printf("Time: %d:%d:%d\n", t2.hour, t2.min, t2.sec)

Output is the same.

See related questions:

https://stackoverflow.com/questions/33040495/golang-operator-overloading/33040529#33040529

https://stackoverflow.com/questions/41477624/copy-instances-of-type-t-when-any-of-the-methods-of-a-named-type-t-have-a-point/41482152#41482152

huangapple
  • 本文由 发表于 2017年6月8日 19:32:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/44434544.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定