มาเริ่มเขียนโค้ดกันเถอะ !!

ดูโค้ดด้านล่างแล้วคิดว่ามันพิมพ์อะไร [%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 เป็นรูปแบบใหม่

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

เราต้องมองจากมุมต่อไปนี้:

  1. พฤติกรรมการดำเนินการเป็นประเภทใหม่

เราต้องการทดสอบว่าประเภทใหม่ทำงานเหมือนกับประเภทดั้งเดิม 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)
}

เนื้อหาการอ่านเพิ่มเติมเกี่ยวกับนามแฝงประเภทและคำจำกัดความประเภท

  1. https://go.dev/talks/2016/refactor.article

ลองเล่นกับตัวอย่างด้วยตัวเองเพราะยังมีอะไรให้สำรวจอีกมากมาย

คุณสามารถพบกับฉันได้ที่ Linkedin 👋🏻👋🏻