ใน Go ฟังก์ชันสามารถยอมรับได้เฉพาะอาร์กิวเมนต์ประเภทที่ระบุในรายการพารามิเตอร์ในข้อกำหนดฟังก์ชัน คุณลักษณะภาษาพารามิเตอร์แบบผันแปรซับซ้อนเล็กน้อย แต่เป็นไปตามกฎที่กำหนดไว้อย่างดี
ลายเซ็นฟังก์ชันสำหรับfmt.Println
คือ:
func Println(a ...interface{}) (n int, err error)
ต่อspecifiction ภาษา ,
พารามิเตอร์ขาเข้าสุดท้ายในลายเซ็นฟังก์ชันอาจมีชนิดที่นำหน้าด้วย .... ฟังก์ชันที่มีพารามิเตอร์ดังกล่าวเรียกว่าตัวแปรและอาจเรียกใช้โดยมีอาร์กิวเมนต์เป็นศูนย์หรือมากกว่าสำหรับพารามิเตอร์นั้น
ซึ่งหมายความว่าคุณสามารถส่งผ่านPrintln
รายการอาร์กิวเมนต์interface{}
ประเภท เนื่องจากทุกประเภทใช้อินเทอร์เฟซว่างคุณจึงสามารถส่งรายการอาร์กิวเมนต์ประเภทใดก็ได้ซึ่งเป็นวิธีที่คุณสามารถโทรได้Println(1, "one", true)
เช่นไม่มีข้อผิดพลาด ดูส่วน"การส่งอาร์กิวเมนต์ไปยัง ... พารามิเตอร์"ของข้อกำหนดภาษา:
ค่าที่ส่งผ่านคือสไลซ์ใหม่ของชนิด [] T ที่มีอาร์เรย์พื้นฐานใหม่ซึ่งมีองค์ประกอบที่ต่อเนื่องกันเป็นอาร์กิวเมนต์ที่แท้จริงซึ่งทั้งหมดจะต้องกำหนดให้กับ T.
ส่วนที่ทำให้คุณมีปัญหาหลังจากนั้นในข้อกำหนด:
หากอาร์กิวเมนต์สุดท้ายสามารถกำหนดให้กับประเภทสไลซ์ [] T อาร์กิวเมนต์อาจถูกส่งต่อโดยไม่เปลี่ยนแปลงเป็นค่าสำหรับพารามิเตอร์ ... T หากอาร์กิวเมนต์ตามด้วย .... ในกรณีนี้จะไม่มีการสร้างชิ้นส่วนใหม่
flag.Args()
[]string
เป็นประเภท ตั้งแต่T
ในPrintln
เป็นinterface{}
, คือ[]T
[]interface{}
ดังนั้นคำถามจึงสรุปได้ว่าค่าสไลซ์ของสตริงสามารถกำหนดให้กับตัวแปรของประเภทส่วนติดต่อได้หรือไม่ คุณสามารถทดสอบได้อย่างง่ายดายใน go code ของคุณโดยพยายามมอบหมายงานตัวอย่างเช่น:
s := []string{}
var i []interface{}
i = s
หากคุณพยายามกำหนดเช่นนั้นคอมไพลเลอร์จะแสดงข้อความแสดงข้อผิดพลาดนี้:
cannot use s (type []string) as type []interface {} in assignment
และนั่นเป็นเหตุผลที่คุณไม่สามารถใช้จุดไข่ปลาหลังสไลซ์สตริงเป็นอาร์กิวเมนต์fmt.Println
ได้ ไม่ใช่บั๊ก แต่ทำงานตามที่ตั้งใจไว้
ยังมีอีกหลายวิธีที่คุณสามารถพิมพ์อยู่flag.Args()
ด้วยPrintln
เช่น
fmt.Println(flag.Args())
(ซึ่งออกจะเป็น[elem0 elem1 ...]
ต่อเอกสารแพคเกจ fmt )
หรือ
fmt.Println(strings.Join(flag.Args(), ` `)
(ซึ่งจะเอาท์พุทองค์ประกอบสไลซ์สตริงซึ่งแต่ละส่วนคั่นด้วยช่องว่างเดียว) โดยใช้ฟังก์ชันเข้าร่วมในแพ็กเกจสตริงที่มีตัวคั่นสตริงเป็นต้น
go run test.go some test flags
) และดูเหมือนว่าจะใช้งานได้เมื่อเปลี่ยนflags.Args()...
เป็น justflag.Args()
(ผลลัพธ์คือ[some test flags]
ตามด้วยบรรทัดใหม่ดูเหมือนว่าจะทำงานร่วมกับการลงทะเบียนแฟล็กจริงด้วย) จะไม่แสร้งทำเป็นเข้าใจว่าทำไมและคำตอบของ Stephen ก็ให้ข้อมูลมากกว่าอยู่ดี :)