มาเริ่มเขียนโค้ดกันเถอะ !!
ดูโค้ดด้านล่างแล้วคิดว่ามันพิมพ์อะไร [%T ใช้เพื่อพิมพ์ข้อมูลประเภท]
package main import "fmt" type int1 = int // OPTION-1 type int2 int // OPTION-2 func main() { var i1 int1 var i2 int2 fmt.Printf("%T, %T", i1, i2) }
เอาต์พุต
int, main.int2
สิ่งที่น่าสนใจคือ i1 พิมพ์ intและ i2พิมพ์ main.int2
เหตุใดเราจึงเห็นผลลัพธ์นี้ ?
i1 เป็นนามแฝง Alias เป็นชื่อที่สองของประเภทที่มีอยู่ และเหมือนกับการแทนที่ int1 ทั้งหมดด้วย int
โดยที่ int2 เป็นคำจำกัดความประเภท สังเกตผลลัพธ์ที่บอกว่า: “main.int2” ความหมายคือ int2 เป็นรูปแบบใหม่
ความแตกต่างคืออะไร?
เราต้องมองจากมุมต่อไปนี้:
- พฤติกรรมการดำเนินการเป็นประเภทใหม่
เราต้องการทดสอบว่าประเภทใหม่ทำงานเหมือนกับประเภทดั้งเดิม int หรือไม่ เมื่อต้องการทำเช่นนี้ เราลองดำเนินการบางอย่างที่ได้รับการสนับสนุนตามประเภท int
package main import "fmt" type int1 = int // OPTION-1 type int2 int // OPTION-2 func main() { var i1 int1 var i2 int2 // Check if integer operations works i1 += 10 i2 += 10 i1 -= 5 i2 -= 5 // check if the new type needs an explicit type conversion var i3 int = i1 var i4 int = i2 fmt.Println(i1, i2, i3, i4) }
เอาต์พุต
./prog.go:21:15: cannot use i2 (variable of type int2) as int value in variable declaration Go build failed.
ซึ่งเป็นไปตามผลลัพธ์ของโปรแกรมแรก ประเภทที่กำหนดใหม่ไม่สามารถกำหนดให้กับ int var ได้ เนื่องจากประเภทของ i2 ไม่ใช่ int แต่เป็น main.int2 แทน ดังนั้นเราจึงจำเป็นต้องมีนักแสดงประเภทที่ชัดเจนตามด้านล่าง และทุกอย่างก็จะทำงานได้ดี
package main import "fmt" type int1 = int // OPTION-1 type int2 int // OPTION-2 func main() { var i1 int1 var i2 int2 // Check if integer operations works i1 += 10 i2 += 10 i1 -= 5 i2 -= 5 // check if the new type needs an explicit type conversion var i3 int = i1 var i4 int = int(i2) // NOTICE HERE !! fmt.Println(i1, i2, i3, i4) }
เอาท์พุต
5 5 5 5
<แข็งแกร่ง>2. การกำหนดการดำเนินงาน/วิธีการใหม่
เรามาลองกำหนดวิธีการในประเภทที่เรากำหนดใหม่กัน
package main import "fmt" type int1 = int // OPTION-1 type int2 int // OPTION-2 func (i int1) ToString() string { return fmt.Sprintf("%d", i) } func (i int2) ToString() string { return fmt.Sprintf("%d", i) } func main() { }
เอาต์พุต
./prog.go:8:7: cannot define new methods on non-local type int
คล้ายกับตัวอย่างก่อนหน้านี้อีกครั้ง รหัสไม่ทำงานและเราได้รับข้อผิดพลาด แต่คราวนี้ ข้อผิดพลาดมีไว้สำหรับนามแฝงประเภทแทนที่จะเป็นประเภทใหม่ที่กำหนดโดยใช้คำจำกัดความประเภท
เนื่องจากการดำเนินการนี้ใช้งานไม่ได้ เราจึงลบเมธอด func (i int1) ToString() string
และพยายามเรียกใช้โค้ดที่เหลือ
package main import "fmt" type int1 = int // OPTION-1 type int2 int // OPTION-2 func (i int2) ToString() string { return fmt.Sprintf("%d", i) } func main() { var i1 int1 var i2 int2 fmt.Println(i1, i2.ToString()) }
เอาต์พุต
0 0
<แข็งแกร่ง>3. การดำเนินการมอบหมาย
เราพบข้อผิดพลาดประการหนึ่งในตัวอย่างที่ 2 ของเรา ซึ่งไม่สามารถกำหนดประเภทที่กำหนดไว้ใหม่ให้กับประเภทต้นแบบเดิมได้ ลองดูอีกด้านหนึ่งตอนนี้
package main import "fmt" type int1 = int // OPTION-1 type int2 int // OPTION-2 func main() { var i1 int1 var i2 int2 const ( c1 = 5 // untyped numeric const c2 int = 10 // typed numeric const ) // assign untyped constant i1 = c1 i2 = c1 // assign a typed constant i1 = c2 i2 = c2 // LINE-23 // assign a typed var var i int = 15 i1 = i i2 = i // LINE-28 fmt.Println(i1, i2) }
เอาต์พุต
./prog.go:23:7: cannot use c2 (constant 10 of type int) as int2 value in assignment ./prog.go:28:7: cannot use i (variable of type int) as int2 value in assignment Go build failed.
"แหล่งที่มา"
ข้อความแสดงข้อผิดพลาดค่อนข้างอธิบายตนเองได้ค่อนข้างมาก
อย่างไรก็ตาม คุณต้องสังเกตว่า i2 = c2
ล้มเหลว ในขณะที่ i2 = c1
ไม่ล้มเหลว นั่นเป็นเพราะ go ทำการจับคู่ประเภทที่เข้มงวด ดังนั้นสำหรับค่าคงที่ที่พิมพ์ (c2) หรือสำหรับตัวแปรที่พิมพ์ (บรรทัดที่ 28) ประเภทจะต้องตรงกัน ในขณะที่สำหรับค่าคงที่ที่ไม่ได้พิมพ์ (c1) ประเภทสามารถอนุมานได้ภายในนิพจน์หากเข้ากันได้
การใช้งาน
พิมพ์นามแฝง
สามารถใช้เพื่อกำหนดชื่ออื่น (นามแฝง 😝) ซึ่งสามารถใช้แทนชื่อเดิมได้ คุณจะทำแบบนั้นเมื่อใด
เมื่อคุณไม่ชอบชื่อประเภทเดิม อาจจะดูเว่อร์เกินไป😉
การทำเช่นนี้อาจมีเหตุผลที่สมเหตุสมผล โปรดดู "เนื้อหาสำหรับอ่าน" ในตอนท้าย
หรือบางทีคุณอาจต้องการบอกให้โลกรู้ว่าคุณเขียนโค้ดนี้ 🤣
package main import "fmt" type gaurav = int func main() { var leangaurav gaurav leangaurav++ fmt.Println(leangaurav) }
คำจำกัดความประเภท
อาจมีเหตุผลอื่นในการใช้คำจำกัดความของประเภท แต่หนึ่งในนั้นคือการใช้คำจำกัดความของประเภทสำหรับพฤติกรรมที่เหมือนกัน enum เช่นเดียวกับตัวอย่างนี้จาก go spec ซึ่งได้รับการแก้ไขเล็กน้อยเพื่อให้เข้าใจง่าย อ่านข้อมูลจำเพาะเพื่ออ่านโค้ดต้นฉบับ
type TimeZone int const ( EST TimeZone = -5 CST TimeZone = -6 MST TimeZone = -7 PST TimeZone = -8 ) func (tz TimeZone) String() string { return fmt.Sprintf("GMT%+dh", tz) }
เนื้อหาการอ่านเพิ่มเติมเกี่ยวกับนามแฝงประเภทและคำจำกัดความประเภท
ลองเล่นกับตัวอย่างด้วยตัวเองเพราะยังมีอะไรให้สำรวจอีกมากมาย
คุณสามารถพบกับฉันได้ที่ Linkedin 👋🏻👋🏻