英文:
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
包。它完美地工作,但是我有两个问题:
-
在我的代码中,为什么在
init_Time
函数中变量(hour,min,sec)的赋值被执行了两次:t.hour, t.min, t.sec = time.Now().Clock()
以及在main()
函数中:
Tm.hour, Tm.min, Tm.sec = init_Time(Tm)
这是必要的还是我的错误?
- 为什么如果我将
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:
-
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?
- 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
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论