doubeng3216 2013-07-11 23:48
浏览 146
已采纳

在Go中实例化类型的首选方法

I like the fact that Go doesn't give me a million ways to do simple things – to borrow from The Zen of Python, “There should be one – and preferably only one – obvious way to do it.”

However, I'm not clear on the preferred/idiomatic way of instantiating types. The basic types are easy:

n := 0
t := 1.5
str := "Hello"

But what about structs? Are the following equivalent, and if so, which is preferred and why?

var f Foo    
f := Foo{}

What about slices? I can do var xs []int, xs := []int{}, or xs := make([]int), but I think the first option (as opposed to with structs) is different from the others? I assume this will also apply to maps.

With pointers, I hear that new should be avoided. Is this good advice, and if so, what would count as a valid usage of new?

I realize that this may partly be a question of style, but a rationale for preferring a particular style would be helpful in any case.

  • 写回答

3条回答 默认 最新

  • dpzzkfb1244 2013-07-12 19:03
    关注

    When you declare a variable, where T is some type:

    var name T
    

    Go gives you a piece of uninitialized "zeroed" memory.

    With primitives, this means that var name int would be 0, and var name string would be "". In C it might be zeroed, or might be something unexpected. Go guarantees an uninitialized variable is the type's zero equivalent.

    Internally slices, maps, and channels are treated as pointers. Pointers zero value is nil, meaning it points to nil memory. Without initializing it, you can encounter a panic if you try to operate on it.

    The make function is specifically designed for a slice, map, or channel. The make function's arguments are:

    make(T type, length int[, capacity int]) // For slices.
    make(T[, capacity int]) // For a map.
    make(T[, bufferSize int]) // For a channel. How many items can you take without blocking?
    

    A slices length is how many items it starts with. The capacity is the allocated memory before a resize is needed (internally, new size * 2, then copy). For more information see Effective Go: Allocation with make.

    Structs: new(T) is equivalent to &T{}, not T{}. *new(T) is equivalent to *&T{}.

    Slices: make([]T,0) is equivalent to []T{}.

    Maps: make(map[T]T) is equivalent to map[T]T{}.

    As far as which method is preferred, I ask myself the following question:

    Do I know the value(s) right now inside the function?

    If the answer is "yes", then I go with one of the above T{...}. If the answer is "no", then I use make or new.

    For example, I would avoid something like this:

    type Name struct {
        FirstName string
        LastName string
    }
    
    func main() {
        name := &Name{FirstName:"John"}
        // other code...
        name.LastName = "Doe"
    }
    

    Instead I would do something like this:

    func main() {
        name := new(Name)
        name.FirstName = "John"
        // other code...
        name.LastName = "Doe"
    }
    

    Why? Because by using new(Name) I make it clear that I intend to fill the values later. If I used &Name{...} it wouldn't be clear that I intended to add/change a value later in the same function without reading the rest of the code.

    The exception is with structs when you don't want a pointer. I'll use T{}, but I won't put anything in it if I plan to add/change the values. Of course *new(T) also works, but that's like using *&T{}. T{} is cleaner in that case, although I tend to use pointers with structs to avoid making a copy when passing it around.

    Another thing to keep in mind, a []*struct is smaller and cheaper to resize than []struct, assuming the struct is much larger than a pointer, which is typically 4 - 8 bytes (8 bytes on 64bit?).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)