ความแตกต่างระหว่าง [] string และ… string ใน golang คืออะไร?


85

ในภาษา Go

[]string เป็นสตริงอาร์เรย์

และเรายังใช้...stringเป็นพารามิเตอร์

อะไรคือความแตกต่าง?

นิยามฟังก์ชัน:

func f(args ...string) {}

ฉันสามารถเรียกใช้ฟังก์ชันนี้ได้หรือไม่?

args := []string{"a", "b"}

f(args)

คำตอบ:


126

[]string เป็นสตริงอาร์เรย์

ในทางเทคนิคแล้วมันคือชิ้นส่วนที่อ้างอิงถึงอาร์เรย์พื้นฐาน

และเรายังใช้...stringเป็นพารามิเตอร์

อะไรคือความแตกต่าง?

ในส่วนของโครงสร้างไม่มีอะไรจริงๆ ชนิดข้อมูลที่เกิดจากไวยากรณ์ทั้งสองเหมือนกัน

...ไวยากรณ์พารามิเตอร์ทำให้พารามิเตอร์ variadic จะยอมรับstringอาร์กิวเมนต์เป็นศูนย์หรือมากกว่าและอ้างอิงเป็นชิ้นส่วน

สำหรับการโทรfคุณสามารถส่งสตริงไปยังพารามิเตอร์ตัวแปรด้วยไวยากรณ์ต่อไปนี้:

func f(args ...string) {
    fmt.Println(len(args))
}


args := []string{"a", "b"}

f(args...)

ไวยากรณ์นี้สามารถใช้ได้สำหรับทั้งชิ้นสร้างขึ้นโดยใช้ไวยากรณ์ที่แท้จริงหรือชิ้นที่เป็นตัวแทนของพารามิเตอร์ variadic (ตั้งแต่มีจริงๆความแตกต่างระหว่างพวกเขาไม่ได้)

http://play.golang.org/p/QWmzgIWpF8


10
[]stringเป็นสไลซ์ไม่ใช่อาร์เรย์ ความแตกต่างระหว่างอาร์เรย์และชิ้นส่วนมีความละเอียดอ่อน แต่มีความสำคัญ
Stephen Weinberg

@StephenWeinberg: ใช่คำตอบที่ "ไม่มีอะไรจริงๆ" ของฉันสำหรับคำพูด "ความแตกต่าง" คือการตอบคำถามที่ถามเกี่ยวกับความแตกต่างระหว่างชิ้นส่วนที่สร้างโดยพารามิเตอร์ฟังก์ชันตัวแปรกับส่วนที่สร้างขึ้นโดยใช้[]stringไวยากรณ์ ฉันจะเพิ่มคำพูดให้กับคำตอบของฉันเพื่อให้ชัดเจนขึ้น :-)
ฉันเกลียดขี้เกียจ

@IHateLazy มีวิธีที่จะทำให้ builtin printlnทำงานกับจุดไข่ปลาได้หรือไม่? ที่นี่คุณจะพบการทดสอบของฉัน หากมีใครต้องการฟังก์ชั่นการพิมพ์แก้จุดบกพร่องไปดู playgound ของฉัน
ห้องนิรภัย

14

ทั้งสองสร้างอาร์เรย์ของสตริง แต่ความแตกต่างอยู่ที่วิธีการเรียก

func f(args ...string) {

}
// Would be called like this:

f("foo","bar","baz");

สิ่งนี้ช่วยให้คุณยอมรับอาร์กิวเมนต์จำนวนตัวแปร (ประเภทเดียวกันทั้งหมด)

ตัวอย่างที่ดีในเรื่องนี้คือfmt.Printและเพื่อน ๆ ซึ่งสามารถยอมรับข้อโต้แย้งน้อยหรือมากเท่าที่คุณต้องการ


ฉันไม่ใช่ผู้เชี่ยวชาญด้าน Go แต่ไม่ใช่อาร์กิวเมนต์ตัวแปรเดียวและอีกอาร์กิวเมนต์อาร์เรย์เดียวและทั้งสองไม่แตกต่างกันเหมือนในภาษาอื่น ๆ ใช่หรือไม่
Lightness Races ใน Orbit

1
@LightnessRacesinOrbit ครับ หากไม่ชัดเจนขออภัยในความสับสน บรรทัดแรกเกี่ยวกับการสร้างอาร์เรย์ทั้งคู่หมายความว่าอาร์กิวเมนต์ที่เป็นผลลัพธ์ในทั้งสองอินสแตนซ์คืออาร์เรย์ เกือบจะเหมือนกับdef fn(*args)โครงสร้างของหลาม
tylerl

ดังนั้น Go จึงแสดงอาร์กิวเมนต์ที่หลากหลายเป็นตัวอย่างของประเภทอาร์เรย์? ที่น่าพอใจ
Lightness Races ใน Orbit

จริงๆแล้วพวกเขาทั้งคู่สร้างสตริงขึ้นมาไม่ใช่อาร์เรย์ พวกเขาเป็นสิ่งที่แตกต่างกันในโกลัง
PointerToConstantChar

ทั้งคู่ไม่ได้สร้างสตริง "อาร์เรย์" แต่จะสร้างสตริง "สไลซ์"
Inanc Gumus


1

ช่วยลดความซับซ้อนของพารามิเตอร์ฟังก์ชันของคุณ นี่คือตัวอย่าง ( https://play.golang.org/p/euMuy6IvaM ): Method SampleEllipsis ยอมรับพารามิเตอร์ประเภทเดียวกันตั้งแต่ศูนย์ถึงหลายพารามิเตอร์ แต่ในเมธอด SampleArray จะต้องประกาศอาร์กิวเมนต์

package main

import "fmt"

func SampleEllipsis(args ...string) {
    fmt.Printf("Sample ellipsis : %+v\n",args)
}


func SampleArray(args []string) {
    fmt.Println("Sample array ")
    SampleEllipsis(args...)
}

func main() {
    // Method one
    SampleEllipsis([]string{"A", "B", "C"}...)
    // Method two
    SampleEllipsis("A", "B", "C")
    // Method three
    SampleEllipsis()

    // Simple array
    SampleArray([]string{"A", "B", "C"})

    // Simple array
    SampleArray([]string{})

}

ผลตอบแทน:

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