Skip to content

Tipe

Di bagian tipe data sebelumnya sudah diperkenalkan secara singkat semua tipe data built-in di Go, tipe dasar built-in ini adalah dasar untuk tipe kustom selanjutnya. Go adalah bahasa tipe statis yang khas, semua tipe variabel akan ditentukan selama periode kompilasi, dan tidak akan berubah lagi sepanjang siklus hidup program, bagian ini akan简单介绍 sistem tipe Go dan penggunaan dasar.

Static Strong Type

Go adalah bahasa static strong type, static berarti semua tipe variabel di Go sudah ditentukan selama kompilasi, tidak akan berubah lagi selama siklus hidup program, meskipun deklarasi variabel pendek di Go agak mirip dengan gaya penulisan bahasa dinamis, tetapi tipe variabelnya disimpulkan oleh compiler, perbedaan paling mendasar adalah setelah tipenya disimpulkan tidak akan berubah lagi, bahasa dinamis justru sebaliknya. Jadi kode di bawah sama sekali tidak dapat dikompilasi, karena a adalah variabel tipe int, tidak dapat assign string.

go
func main() {
  var a int = 64
  a = "64"
  fmt.Println(a) // cannot use "64" (untyped string constant) as int value in assignment
}

Strong type berarti melakukan type checking yang ketat dalam program, saat terjadi ketidakcocokan tipe, akan segera memberi tahu programmer bahwa tidak boleh melakukan seperti ini, bukan seperti bahasa dinamis yang mencoba menyimpulkan hasil yang mungkin. Jadi kode di bawah tidak dapat dikompilasi, karena kedua tipe berbeda, tidak dapat melakukan operasi.

go
func main() {
  fmt.Println(1 + "1") // invalid operation: 1 + "1" (mismatched types untyped int and untyped string)
}

Type Suffix

Mengapa Go menempatkan deklarasi tipe di belakang bukan di depan, sebagian besar belajar dari pelajaran C, ambil contoh官方 untuk menampilkan efek, ini adalah function pointer

c
int (*(*fp)(int (*)(int, int), int))(int, int)

Jujur tidak serius melihat sulit mengetahui ini adalah tipe apa, di Go penulisan serupa sebagai berikut

go
f func(func(int,int) int, int) func(int, int) int

Gaya deklarasi Go selalu mengikuti prinsip nama di depan, tipe di belakang, baca dari kiri ke kanan, kira-kira sekilas sudah dapat mengetahui ini adalah fungsi, dan nilai return adalah func(int,int) int. Saat tipe menjadi semakin kompleks, type suffix dalam keterbacaan jauh lebih baik, Go dalam banyak aspek desain adalah untuk keterbacaan.

Deklarasi Tipe

Di Go melalui deklarasi tipe, dapat mendeklarasikan tipe baru dengan nama kustom, mendeklarasikan tipe baru biasanya memerlukan nama tipe dan tipe dasar, contoh sederhana sebagai berikut:

go
type MyInt int64

Di deklarasi tipe di atas, melalui keyword type mendeklarasikan tipe bernama MyInt dengan tipe dasar int64. Di Go, setiap tipe yang dideklarasikan baru harus memiliki tipe dasar yang sesuai, dan nama tipe tidak disarankan duplikat dengan identifier built-in yang sudah ada.

go
type MyInt int64

type MyFloat64 float64

type MyMap map[string]int

// Dapat dikompilasi, tetapi tidak disarankan menggunakan, ini akan menimpa tipe asli
type int int64

Tipe yang dideklarasikan melalui deklarasi tipe semuanya adalah tipe baru, tipe berbeda tidak dapat melakukan operasi, meskipun tipe dasarnya sama.

go
type MyFloat64 float64

var f1 MyFloat64
var f float64
f1 = 0.2
f = 0.1
fmt.Println(f1 + f)
go
invalid operation: f1 + f (mismatched types MyFloat64 and float64)

Alias Tipe

Alias tipe berbeda dengan deklarasi tipe, alias tipe hanya alias, bukan membuat tipe baru, contoh sederhana sebagai berikut:

go
type Int = int

Keduanya adalah tipe yang sama, hanya nama yang berbeda, jadi juga dapat melakukan operasi, jadi contoh di bawah secara alami dapat dikompilasi.

go
type Int = int
var a Int = 1
var b int = 2
fmt.Println(a + b)
3

Alias tipe sangat berguna untuk beberapa tipe yang sangat kompleks, misalnya sekarang ada tipe map[string]map[string]int, ini adalah map dua dimensi, sekarang ada parameter fungsi adalah tipe map[string]map[string]int, sebagai berikut

go
func PrintMyMap(mymap map[string]map[string]int) {
   fmt.Println(mymap)
}

Dalam kasus ini, tidak perlu menggunakan deklarasi tipe, karena yang前者 adalah mendeklarasikan tipe baru, tidak dapat sebagai parameter fungsi ini, contoh setelah menggunakan alias tipe sebagai berikut

go
type TwoDMap = map[string]map[string]int

func PrintMyMap(mymap TwoDMap) {
   fmt.Println(mymap)
}

Setelah menggunakan alias tipe terlihat lebih ringkas.

TIP

Tipe built-in any adalah alias tipe interface{}, keduanya sepenuhnya ekuivalen, hanya sebutan berbeda.

Konversi Tipe

Di Go, hanya ada konversi tipe eksplisit, tidak ada konversi tipe implisit, oleh karena itu variabel tipe berbeda tidak dapat melakukan operasi, tidak dapat sebagai parameter传递. Prasyarat konversi tipe adalah mengetahui tipe variabel yang dikonversi dan tipe target yang akan dikonversi, contoh sebagai berikut:

go
type MyFloat64 float64

var f1 MyFloat64
var f float64
f1 = 0.2
f = 0.1
fmt.Println(float64(f1) + f)
0.30000000000000004

Melalui konversi tipe eksplisit MyFloat64 menjadi tipe float64, baru dapat melakukan operasi penjumlahan. Prasyarat lain konversi tipe adalah: tipe yang dikonversi harus dapat direpresentasikan oleh tipe target (Representability), misalnya int dapat direpresentasikan oleh tipe int64, juga dapat direpresentasikan oleh tipe float64, jadi di antara mereka dapat melakukan konversi tipe eksplisit, tetapi tipe int tidak dapat direpresentasikan oleh tipe string dan bool, karena itu juga tidak dapat melakukan konversi tipe.

TIP

Tentang definisi Representability dapat前往 Referensi Manual - Representability untuk了解 lebih banyak detail.

Meskipun dua tipe dapat saling merepresentasikan, hasil konversi tipe juga tidak selalu benar, lihat contoh berikut:

go
var num1 int8 = 1
var num2 int32 = 512
fmt.Println(int32(num1), int8(num2))
1 0

num1 dengan benar dikonversi menjadi tipe int32, tetapi num2 tidak. Ini adalah masalah numeric overflow yang khas, int32 dapat merepresentasikan integer 31 bit, int8 hanya dapat merepresentasikan integer 7 bit, integer presisi tinggi saat dikonversi ke integer presisi rendah akan membuang bit tinggi menyimpan bit rendah, oleh karena itu hasil konversi num1 adalah 0. Dalam konversi tipe numerik, biasanya disarankan kecil ke besar, tidak disarankan besar ke kecil.

Saat menggunakan konversi tipe, untuk beberapa tipe perlu menghindari ambiguitas, contoh sebagai berikut:

go
*Point(p) // setara dengan *(Point(p))
(*Point)(p)  // mengkonversi p menjadi tipe *Point
<-chan int(c)    // setara dengan <-(chan int(c))
(<-chan int)(c)  // mengkonversi c menjadi tipe  <-chan int
(func())(x)      // mengkonversi x menjadi tipe func()
(func() int)(x)  // mengkonversi x menjadi tipe func() int

Type Assertion

Type assertion biasanya用于判断 apakah variabel tipe interface tertentu adalah tipe tertentu, contoh sebagai berikut

go
var b int = 1
var a interface{} = b
if intVal, ok := a.(int); ok {
   fmt.Println(intVal)
} else {
   fmt.Println("error type")
}
1

Karena interface{} adalah tipe empty interface, tipe empty interface dapat merepresentasikan semua tipe, tetapi tipe int tidak dapat merepresentasikan tipe interface{}, jadi tidak dapat menggunakan konversi tipe. Sedangkan type assertion dapat判断 apakah tipe dasarnya adalah tipe yang diinginkan, statement type assertion memiliki dua nilai return, satu adalah nilai setelah konversi tipe, yang lain adalah nilai boolean hasil konversi.

Type Switch

Di Go, statement switch juga mendukung gaya penulisan khusus, melalui gaya penulisan ini dapat membuat logika yang berbeda sesuai case yang berbeda, prasyarat penggunaan adalah parameter input harus tipe interface, contoh sebagai berikut:

go
var a interface{} = 2
switch a.(type) {
    case int: fmt.Println("int")
    case float64: fmt.Println("float")
    case string: fmt.Println("string")
}
int

TIP

Melalui operasi yang disediakan paket unsafe, dapat绕过 sistem tipe Go, dapat melakukan operasi konversi tipe yang semula tidak dapat dikompilasi.

Golang by www.golangdev.cn edit