เริ่มต้นโครงสร้างที่ซ้อนกัน


125

ฉันไม่สามารถหาวิธีเริ่มต้นโครงสร้างที่ซ้อนกันได้ ดูตัวอย่างได้ที่นี่: http://play.golang.org/p/NL6VXdHrjh

package main

type Configuration struct {
    Val   string
    Proxy struct {
        Address string
        Port    string
    }
}

func main() {

    c := &Configuration{
        Val: "test",
        Proxy: {
            Address: "addr",
            Port:    "80",
        },
    }

}

1
เพียงแค่เรียนรู้ไปและมีคำถามเดียวกัน คุณสามารถละเว้นประเภทองค์ประกอบสำหรับอาร์เรย์และแผนที่ได้ แต่ไม่ใช่สำหรับโครงสร้างที่ซ้อนกัน ไร้เหตุผลและไม่สะดวก ใครช่วยอธิบายว่าทำไม?
Peter Dotchev

คำตอบ:


178

มีเหตุผลเฉพาะใดที่จะไม่ทำให้ Proxy เป็นโครงสร้างของตัวเอง?

อย่างไรก็ตามคุณมี 2 ตัวเลือก:

วิธีที่เหมาะสมเพียงแค่ย้ายพร็อกซีไปยังโครงสร้างของตัวเองเช่น:

type Configuration struct {
    Val string
    Proxy Proxy
}

type Proxy struct {
    Address string
    Port    string
}

func main() {

    c := &Configuration{
        Val: "test",
        Proxy: Proxy{
            Address: "addr",
            Port:    "port",
        },
    }
    fmt.Println(c)
    fmt.Println(c.Proxy.Address)
}

วิธีที่เหมาะสมและน่าเกลียดน้อยกว่า แต่ยังใช้งานได้:

c := &Configuration{
    Val: "test",
    Proxy: struct {
        Address string
        Port    string
    }{
        Address: "addr",
        Port:    "80",
    },
}

1
ในวิธีที่สองเราสามารถหลีกเลี่ยงนิยามโครงสร้างซ้ำ ๆ ได้หรือไม่?
Gaurav Ojha

@GauravOjha ไม่ใช่ตลอดทาง แต่มีบางอย่างเช่นplay.golang.org/p/n24BD3NlIR
OneOfOne

ฉันคิดว่าการใช้ประเภทฝังตัวนั้นเหมาะกว่าสำหรับความสัมพันธ์แบบ is-a
crackerplace

ดังที่ระบุไว้ด้านล่างโดย @sepehr คุณสามารถเข้าถึงตัวแปรได้โดยตรงโดยใช้สัญกรณ์จุด
snassr

จะเกิดอะไรขึ้นถ้าพร็อกซีมีฟิลด์ที่มีโครงสร้างเป็นประเภท? วิธีการเริ่มต้นภายในโครงสร้างที่ซ้อนกันอื่น?
kucinghitam

90

หากคุณไม่ต้องการใช้นิยามโครงสร้างแยกต่างหากสำหรับโครงสร้างที่ซ้อนกันและคุณไม่ชอบวิธีที่สองที่แนะนำโดย @OneOfOne คุณสามารถใช้วิธีที่สามนี้:

package main
import "fmt"
type Configuration struct {
    Val   string
    Proxy struct {
        Address string
        Port    string
    }
}

func main() {
    c := &Configuration{
        Val: "test",
    }

    c.Proxy.Address = `127.0.0.1`
    c.Proxy.Port = `8080`
}

คุณสามารถตรวจสอบได้ที่นี่: https://play.golang.org/p/WoSYCxzCF2


8
ว้าวคำตอบที่แท้จริงสำหรับคำถามเกี่ยวกับวิธีเริ่มต้นโครงสร้างที่ซ้อนกัน
สูงสุด

1
นี่เป็นสิ่งที่ดีจริง ๆ แต่จะดีกว่านี้ถ้าเราทำได้ในบรรทัดเดียว!
Gaurav Ojha

1
ฉันกำลังมองหาวิธีที่คุณไม่จำเป็นต้องทำ c.Proxy.Address = `127.0.0.1` c.Proxy.Port = `8080` มีวิธีเริ่มต้นค่าเหล่านั้นระหว่างการ&Configuration{}มอบหมายงานหรือไม่?
Matheus Felipe

1
@MatheusFelipe คุณสามารถทำได้ แต่คุณต้องกำหนดProxyเป็นโครงสร้างของตัวเองดูวิธีแรกในคำตอบโดย @OneOfOne
sepehr

IMO ดีกว่าคำตอบที่ยอมรับ
domoarigato

14

กำหนดโครงสร้างของคุณProxyแยกจากกันภายนอกConfigurationดังนี้:

type Proxy struct {
    Address string
    Port    string
}

type Configuration struct {
    Val string
    P   Proxy
}

c := &Configuration{
    Val: "test",
    P: Proxy{
        Address: "addr",
        Port:    "80",
    },
}

ดูhttp://play.golang.org/p/7PELCVsQIc


ถ้าP Proxyอาร์เรย์คืออะไร?
ErtuğrulAltınboğa


9

gotcha หนึ่งเกิดขึ้นเมื่อคุณต้องการสร้างอินสแตนซ์ประเภทสาธารณะที่กำหนดไว้ในแพ็กเกจภายนอกและประเภทนั้นฝังประเภทอื่นที่เป็นส่วนตัว

ตัวอย่าง:

package animals

type otherProps{
  Name string
  Width int
}

type Duck{
  Weight int
  otherProps
}

คุณสร้างอินสแตนซ์Duckในโปรแกรมของคุณเองได้อย่างไร? นี่คือสิ่งที่ดีที่สุดที่ฉันสามารถทำได้:

package main

import "github.com/someone/animals"

func main(){
  var duck animals.Duck
  // Can't instantiate a duck with something.Duck{Weight: 2, Name: "Henry"} because `Name` is part of the private type `otherProps`
  duck.Weight = 2
  duck.Width = 30
  duck.Name = "Henry"
}

สำหรับคนที่ลืมอย่างฉันให้ตั้งชื่อแอตทริบิวต์ struct ของคุณด้วยตัวพิมพ์ใหญ่ไม่เช่นนั้นคุณจะพบcannot refer to unexported field or method ข้อผิดพลาด
tagaism

5

คุณยังสามารถจัดสรรโดยใช้newและเริ่มต้นฟิลด์ทั้งหมดด้วยมือ

package main

type Configuration struct {
    Val   string
    Proxy struct {
        Address string
        Port    string
    }
}

func main() {
    c := new(Configuration)
    c.Val = "test"
    c.Proxy.Address = "addr"
    c.Proxy.Port = "80"
}

ดูในสนามเด็กเล่น: https://play.golang.org/p/sFH_-HawO_M


2

คุณสามารถกำหนดโครงสร้างและสร้างวัตถุในโครงสร้างอื่นเช่นที่ฉันได้ทำด้านล่าง:

package main

import "fmt"

type Address struct {
    streetNumber int
    streetName   string
    zipCode      int
}

type Person struct {
    name    string
    age     int
    address Address
}

func main() {
    var p Person
    p.name = "Vipin"
    p.age = 30
    p.address = Address{
        streetName:   "Krishna Pura",
        streetNumber: 14,
        zipCode:      475110,
    }
    fmt.Println("Name: ", p.name)
    fmt.Println("Age: ", p.age)
    fmt.Println("StreetName: ", p.address.streetName)
    fmt.Println("StreeNumber: ", p.address.streetNumber)
}

หวังว่าจะช่วยคุณได้ :)


2

คุณต้องกำหนดโครงสร้างที่ไม่มีชื่อใหม่ในระหว่าง &Configuration{}

package main

import "fmt"

type Configuration struct {
    Val   string
    Proxy struct {
        Address string
        Port    string
    }
}

func main() {

    c := &Configuration{
        Val: "test",
        Proxy: struct {
            Address string
            Port    string
        }{
            Address: "127.0.0.1",
            Port:    "8080",
        },
    }
    fmt.Println(c)
}

https://play.golang.org/p/Fv5QYylFGAY

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.