Система типов языка Go в деталях

Go
Система типов языка Go в деталях

Это 18-я статья из серии "Изучаем язык Go".

что такое тип

Концепция типов различается в разных языках программирования и может быть выражена по-разному, но в целом имеет некоторые общие черты.

  1. Тип — это набор значений;
  2. Какие операции можно выполнять между значениями одного типа, например: типы int могут выполнять такие операции, как + и -, а для символьных типов могут выполняться такие операции, как конкатенация и проверка на null;

Таким образом, система языковых типов указывает, какие операторы допустимы для каких типов.

Система типов языка Go

boolean, numeric и string — основные типы данных Go, также известные какПредварительно объявленный тип(предварительно объявленный тип), который можно использовать для создания других типов, таких как литеральные типы.

литеральный тип(литерал типа): он состоит из предварительно объявленных типов (не определенных ключевым словом type), например: [3]int, chan int, map[string] string, *int и т. д.

Создается из литеральных типовсоставной тип, такие как: массив, структура, карта, срез, канал, функция, интерфейс и т. д.

Именованные и безымянные типы

Типы с именами: предварительно объявленные типы, такие как int, int64, float32, string, bool и т. д. Кроме того, любой тип, объявленный с помощью ключевого слова type, также называется именованным типом.

var i int // named type
type myInt int // named type
var b bool // named type

Безымянные типы. Упомянутые выше составные типы, включая массив, структуру, указатель, функцию, интерфейс, срез, карту и канал, являются безымянными типами. У них нет имен, но есть буквальные описания того, как они составлены.

[]string // unnamed type
map[string]string // unnamed type
[10]int // unnamed type

базовый тип

У каждого типа есть базовый тип, и если T является предварительно объявленным типом или литеральным типом, базовым типом является сам T; в противном случае базовым типом T является базовый тип типа, на который T ссылается во время определения.

type A string      // string
type B A			// string
type M map[string]int // map[string]int
type N M			// map[string]int
type P *N			// *N
type S string		// string
type T map[S]int	// map[S]int
type U T 			// map[S]int

Строки 1 и 6, предварительно объявленный строковый тип, поэтому базовым типом является сам T, который является строкой;

Строки 3 и 5 являются литеральными типами, поэтому базовым типом является сам T, а именно map[string]int и указатель *N. Примечание: литеральные типы также являются безымянными типами;

В строках 2, 4 и 8 базовый тип T является базовым типом типа, на который ссылается T, когда он определен, например: B ссылается на A, поэтому базовый тип B является строковым типом, и то же верно и для других случаев;

Давайте еще раз посмотрим на пример в строке 7: type T map[S]int , так как базовым типом S является строка, не должен ли базовый тип T быть map[string]int вместо map[S]int на данном этапе. время? Поскольку мы говорим о базовом безымянном типе map[S]int , мы переходим к безымянному типу, как сказано в спецификации языка Go: если T является буквальным типом, соответствующий базовый тип — это сам T.

уступчивость

Присваиваемость переменных была четко указана в документации языка Go.Давайте рассмотрим одну из наиболее важных: когда переменная a может быть присвоена переменной типа T,Оба должны иметь один и тот же базовый тип, и по крайней мере один из них не является именованным типом..

посмотри на код

package main

type aInt int

func main() {
    var i int = 10
    var ai aInt = 100
    i = ai
    printAiType(i)
}

func printAiType(ai aInt) {
    print(ai)
}

Приведенный выше код не компилируется, и при компиляции сообщается об ошибке:

8:4: cannot use ai (type aInt) as type int in assignment
9:13: cannot use i (type int) as type aInt in argument to printAiType

Поскольку i — это именованный тип int, а ai — именованный тип aInt, хотя их базовые типы одинаковы, оба они являются int.

package main

type MyMap map[int]int

func main() {
    m := make(map[int]int)
    var mMap MyMap
    mMap = m
    printMyMapType(mMap)
    print(m)
}

func printMyMapType(mMap MyMap) {
    print(mMap)
}

Приведенный выше код компилируется, потому что m — безымянный тип, а базовый тип m и mMap — один и тот же.

преобразование типов

Посмотрите на спецификацию преобразования типов

类型转化规范

package main

type Meter int64

type Centimeter int32

func main() {
    var cm Centimeter = 1000
    var m Meter
    m = Meter(cm)
    print(m)
    cm = Centimeter(m)
    print(cm)
}

Приведенный выше код компилируется нормально, потому чтоMeterа такжеCentimeterОба являются целыми числами, и их базовые типы могут быть преобразованы друг в друга.

согласованность типов

Эти два типа либо одинаковые, либо разные.

Определенный тип всегда отличается от любого другого типа. Так что даже заранее объявленные именованные типы int, int64 и т. д. не совпадают.

Давайте посмотрим на правило преобразования для структур:

Когда x присваивается T, независимо от метки структуры, x и T должны иметь один и тот же базовый тип.

package main

type Meter struct {
    value int64
}

type Centimeter struct {
    value int32
}

func main() {
    cm := Centimeter{
        value: 1000,
    }

    var m Meter
    m = Meter(cm)
    print(m.value)
    cm = Centimeter(m)
    print(cm.value)
}

Помните это:тот же базовый тип. Поскольку базовым типом члена Meter.value является int64, а базовым типом члена Centimeter.value является int32, они не совпадают, посколькуОпределенный тип всегда отличается от любого другого типа. Таким образом, приведенный выше фрагмент кода компилируется с ошибкой.

package main

type Meter struct {
    value int64
}

type Centimeter struct {
    value int64
}

func main() {
    cm := Centimeter{
        value: 1000,
    }

    var m Meter
    m = Meter(cm)
    print(m.value)
    cm = Centimeter(m)
    print(cm.value)
}

Базовые типы членов Meter.value и Centimeter.value оба являются int64, поэтому они одинаковы, и компиляция может пройти.

ps: первая статья, которую я перевел в GCTT (группа китайских переводчиков Go), была о системе типов языка Go. Сегодня я организую ее для всеобщего обозрения. Надеюсь, эта статья поможет вам понять систему типов Go!


(Конец полного текста)

Оригинал статьи, если нужно перепечатать, указывайте источник!
Добро пожаловать, чтобы отсканировать код и подписаться на официальный аккаунт »Голанг здесь” или двигатьсяseekload.net, см. больше замечательных статей.

Публичная учетная запись «Голанг идет» подготовила для вас подарочный пакет для изучения тайны, и ответьте на [электронную книгу] в фоновом режиме, чтобы получить его!

公众号二维码