为了账号安全,请及时绑定邮箱和手机立即绑定

Go 中的面向对象编程——使用“new”关键字还是不使用?

Go 中的面向对象编程——使用“new”关键字还是不使用?

Go
神不在的星期二 2021-11-22 18:11:48
好吧,我至少可以告诉你你在做什么。bindQuery需要一个指针。它更改存储在地址中的值。你基本上做的是这样的:package mainimport "fmt"func main() {    var q int    myInts := make([]*int, 0, 5)    for i := 0; i < 5; i++ {        q = i        fmt.Printf("%d ", q)        myInts = append(myInts, &q)    }    fmt.Printf("\n")    for _, value := range myInts {        fmt.Printf("%d ", *value)    }    fmt.Printf("\n")    fmt.Println(myInts)}正如您可能猜到的那样,它为您提供了以下信息:0 1 2 3 4 4 4 4 4 4 [0x104382e0 0x104382e0 0x104382e0 0x104382e0 0x104382e0]事情变得有点混乱reflect。您可以将您的类型作为接口,但仅此而已(除非您想使用unsafe)。简单来说,接口包含一个指向底层原始类型(以及其他一些东西)的指针。所以在你的函数中你传递了一个指针(和其他一些东西)。然后你要附加指针。只是具体化并键入 switch 您的界面可能会很好。我假设你知道它可能是什么类型。在这种情况下,您必须按照以下方式进行操作:package mainimport (    "fmt"    "reflect")type foo struct {    fooval string}type bar struct {    barval string}func main() {    f1 := foo{"hi"}    f2 := &foo{"hi"}    b1 := bar{"bye"}    b2 := &bar{"bye"}    doSomething(f1)    doSomething(f2)    doSomething(b1)    doSomething(b2)}func doSomething(i interface{}) {    n := reflect.TypeOf(i)    // get a new one    newn := reflect.New(n).Interface()    // find out what we got and handle each case    switch t := newn.(type) {    case **foo:        *t = &foo{"hi!"}        fmt.Printf("It was a **foo, here is the address %p and here is the value %v\n", *t, **t)    case **bar:        *t = &bar{"bye :("}        fmt.Printf("It was a **bar, here is the address %p and here is the value %v\n", *t, **t)    case *foo:        t = &foo{"hey!"}        fmt.Printf("It was a *foo, here is the address %p and here is the value %v\n", t, *t)    case *bar:        t = &bar{"ahh!"}        fmt.Printf("It was a *bar, here is the address %p and here is the value %v\n", t, *t)    default:        panic("AHHHH")    }}您也可以继续value = reflect.New(query.structType).Interface()在循环内部调用,每次都会为您提供新的接口。每次追加后重新分配值。上次通过循环会使一个额外的虽然..
查看完整描述

1 回答

?
慕侠2389804

TA贡献1719条经验 获得超6个赞

不想NewThing给ThingFactory。


不要创建NewThing函数,除非你有复杂的初始化,或者你故意不导出结构的一部分。选择性地只设置结构的一部分并不复杂,可以通过使用标签来完成。复杂的是“槽 Q 的值取决于槽 Zorb 的值”。未导出的结构字段对于信息隐藏很有用,但应谨慎使用。


Go 是垃圾收集的,任何未被引用的数据都有资格被收集。开始时不用担心它,然后确保清除对不再感兴趣的数据的任何引用,以避免意外活跃(“意外活跃”本质上是“内存泄漏”的 GC 等价物”)。


如果您希望经常打印数据结构,请考虑String为它们创建一个方法(这与您所做的打印并不完全对应,但通常可能对向量更有用):


func (v Vector) String() string {

  return fmt.Sprintf("V<%d, %d, %d>", v.x v.y, v.z);

}

除非“vect”对您来说真的很重要,否则更喜欢“v”或“vector”作为名称。


查看完整回答
反对 回复 2021-11-22
  • 1 回答
  • 0 关注
  • 154 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信