Как конвертировать типы данных в Go

Вступление

В Go типы данных используются для классификации одного конкретного типа данных, определения значений, которые вы можете назначить типу, и операций, которые вы можете выполнять над ним. При программировании бывают случаи, когда вам нужно преобразовывать значения между типами, чтобы манипулировать значениями по-другому. Например, вам может потребоваться объединить числовые значения со строками или представить десятичные разряды в числах, которые были инициализированы как целочисленные значения. Сгенерированным пользователем данным часто автоматически присваивается строковый тип данных, даже если он состоит из чисел; для выполнения математических операций с этим вводом вам необходимо преобразовать строку в числовой тип данных.

Так как Go - язык со статической типизацией,data types are bound to variables, а не значения. Это означает, что если вы определяете переменную какint, она может быть толькоint; вы не можете присвоить емуstring без преобразования типа данных переменной. Статическая природа типов данных в Go придает еще большее значение изучению способов их преобразования.

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

Преобразование типов чисел

Go имеет несколько числовых типов на выбор. В первую очередь они делятся на два основных типа:integers иfloating-point numbers.

Есть много ситуаций, в которых вы можете захотеть конвертировать между числовыми типами. Преобразование междуdifferent sizes of numeric types может помочь оптимизировать производительность для определенных типов системной архитектуры. Если у вас есть целое число из другой части вашего кода и вы хотите разделить его, вы можете преобразовать целое число в число с плавающей точкой, чтобы сохранить точность операции. Кроме того, работа с длительностями времени обычно включает в себя целочисленное преобразование. Чтобы справиться с этими ситуациями, Go имеет встроенныйtype conversions для большинства числовых типов.

Преобразование между целочисленными типами

Go имеет много целочисленных типов данных для выбора. Когда использовать одно вместо другого, обычно больше примерноperformance; однако будут случаи, когда вам нужно будет преобразовать один целочисленный тип в другой. Например, Go иногда автоматически генерирует числовые значения какint, которые могут не соответствовать вашему входному значению. Если бы ваше входное значение былоint64, вы не смогли бы использовать числаint иint64 в одном и том же математическом выражении, пока вы не преобразовали их типы данных в соответствие.

Предположим, у вас естьint8, и вам нужно преобразовать его вint32. Вы можете сделать это, обернув его в преобразование типаint32():

var index int8 = 15

var bigIndex int32

bigIndex = int32(index)

fmt.Println(bigIndex)
Output15

Этот блок кода определяетindex как тип данныхint8 иbigIndex как тип данныхint32. Чтобы сохранить значениеindex вbigIndex, он преобразует тип данных вint32. Это делается путем обертывания преобразованияint32() вокруг переменнойindex.

Чтобы проверить свои типы данных, вы можете использовать инструкциюfmt.Printf и команду%T со следующим синтаксисом:

fmt.Printf("index data type:    %T\n", index)
fmt.Printf("bigIndex data type: %T\n", bigIndex)
Outputindex data type:    int8
bigIndex data type: int32

Поскольку здесь используется глагол%T, оператор печати выводит тип переменной, а не фактическое значение переменной. Таким образом, вы можете подтвердить преобразованный тип данных.

Вы также можете преобразовать большее целочисленное значение в меньшее целое число:

var big int64 = 64

var little int8

little = int8(big)

fmt.Println(little)
Output64

Имейте в виду, что при преобразовании целых чисел вы потенциально можете превысить максимальное значение типа данных иwraparound:

var big int64 = 129
var little = int8(big)
fmt.Println(little)
Output-127

Обтекание происходит, когда значение преобразуется в тип данных, который слишком мал для его хранения. В предыдущем примере 8-битный тип данныхint8 не имел достаточно места для хранения 64-битной переменнойbig. Следует всегда соблюдать осторожность при преобразовании типа данных с большим числом в тип данных с меньшим числом, чтобы избежать случайного усечения данных.

Преобразование целых чисел в числа с плавающей точкой

Преобразование целых чисел в числа с плавающей точкой в ​​Go похоже на преобразование одного целочисленного типа в другой. Вы можете использовать встроенные преобразования типов, обернувfloat64() илиfloat32() вокруг целого числа, которое вы конвертируете:

var x int64 = 57

var y float64 = float64(x)

fmt.Printf("%.2f\n", y)
Output57.00

Этот код объявляет переменнуюx типаint64 и инициализирует ее значение57.

var x int64 = 57

Обертывание преобразованияfloat64() вокругx преобразует значение57 в значение с плавающей запятой57.00.

var y float64 = float64(x)

Команда печати%.2f указываетfmt.Printf форматировать число с плавающей запятой с двумя десятичными знаками.

Вы также можете использовать этот процесс для переменной. Следующий код объявляетf равным57, а затем распечатывает новое значение с плавающей запятой:

var f float64 = 57
fmt.Printf("%.2f\n", f)
Output57.00

Используяfloat32() илиfloat64(), вы можете преобразовать целые числа в числа с плавающей запятой. Далее вы узнаете, как преобразовать числа с плавающей точкой в ​​целые числа.

Преобразование числа с плавающей точкой в ​​целые числа

Go может преобразовывать числа с плавающей точкой в ​​целые числа, но программа теряет точность числа с плавающей точкой.

Обертывание чисел с плавающей запятой вint() или в один из его архитектурно-независимых типов данных работает аналогично тому, как вы использовали его для преобразования из одного целочисленного типа в другой. Вы можете добавить число с плавающей точкой в ​​скобках, чтобы преобразовать его в целое число:

var f float64 = 390.8
var i int = int(f)

fmt.Printf("f = %.2f\n", f)
fmt.Printf("i = %d\n", i)
Outputf = 390.80
i = 390

Этот синтаксис преобразует число с плавающей запятой390.8 в целое число390, отбрасывая десятичный разряд.

Вы также можете использовать это с переменными. Следующий код объявляетb равным125.0 иc как равным390.8, а затем выводит их как целые числа. Краткое объявление переменной (:=) сокращает синтаксис:

b := 125.0
c := 390.8

fmt.Println(int(b))
fmt.Println(int(c))
Output125
390

При преобразовании чисел с плавающей запятой в целые числа с типомint() Go обрезает десятичное и оставшееся числа числа с плавающей запятой для создания целого числа. Обратите внимание: даже если вы захотите округлить 390,8 до 391, Go не будет делать этого через типint(). Вместо этого он опустит десятичную дробь.

Числа, преобразованные через деление

При делении целочисленных типов в Go результатом также будет целочисленный тип, с отброшеннымmodulus или остатком:

a := 5 / 2
fmt.Println(a)
Output2

Если при делении любой из числовых типов является плавающим, то все типы будут автоматически объявлены как плавающие:

    a := 5.0 / 2
    fmt.Println(a)
Output2.5

Это делит число с плавающей запятой5.0 на целое число2, а ответ2.5 представляет собой число с плавающей запятой, которое сохраняет десятичную точность.

В этом разделе вы конвертировали данные разных типов, в том числе целые и числа с плавающей точкой. Далее вы узнаете, как конвертировать числа и строки.

Преобразование со строками

string - это последовательность из одного или нескольких символов (букв, цифр или символов). Строки являются распространенной формой данных в компьютерных программах, и вам может понадобиться преобразовывать строки в числа или числа в строки довольно часто, особенно когда вы принимаете пользовательские данные.

Преобразование чисел в строки

Вы можете преобразовывать числа в строки, используя методstrconv.Itoa из пакетаstrconv в стандартной библиотеке Go. Если вы передадите число или переменную в скобки метода, это числовое значение будет преобразовано в строковое значение.

Во-первых, давайте посмотрим на преобразование целых чисел. Чтобы преобразовать целое число12 в строковое значение, вы можете передать12 в методstrconv.Itoa:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    a := strconv.Itoa(12)
    fmt.Printf("%q\n", a)
}

При запуске этой программы вы получите следующий вывод:

Output"12"

Кавычки вокруг числа 12 означают, что число больше не является целым числом, а теперь является строковым значением.

Вы использовали оператор присваивания:= как для объявления новой переменной с именемa, так и для присвоения значения, возвращаемого функциейstrconv.Itoa(). В этом случае вы присвоили переменной значение12. Вы также использовали глагол%q в функцииfmt.Printf, который предписывает функции заключать указанную строку в кавычки.

С помощью переменных вы можете начать понимать, насколько практичным может быть преобразование целых чисел в строки. Допустим, вы хотите отслеживать ежедневный прогресс пользователя в программировании и вводите, сколько строк кода они пишут за раз. Вы хотели бы показать этот отзыв пользователю и одновременно распечатывать строковые и целочисленные значения:

package main

import (
    "fmt"
)

func main() {
    user := "Sammy"
    lines := 50

    fmt.Println("Congratulations, " + user + "! You just wrote " + lines + " lines of code.")
}

Когда вы запустите этот код, вы получите следующую ошибку:

Outputinvalid operation: ("Congratulations, " + user + "! You just wrote ") + lines (mismatched types string and int)

Вы не можете объединять строки и целые числа в Go, поэтому вам придется преобразовать переменнуюlines в строковое значение:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    user := "Sammy"
    lines := 50

    fmt.Println("Congratulations, " + user + "! You just wrote " + strconv.Itoa(lines) + " lines of code.")
}

Теперь, когда вы запустите код, вы получите следующий вывод, который поздравляет вашего пользователя с его прогрессом:

OutputCongratulations, Sammy! You just wrote 50 lines of code.

Если вы хотите преобразовать число с плавающей точкой в ​​строку, а не в целое число в строку, выполните аналогичные шаги и формат. Когда вы передаете float методуfmt.Sprint из пакетаfmt в стандартной библиотеке Go, будет возвращено строковое значение float. Вы можете использовать либо само значение с плавающей точкой, либо переменную:

package main

import (
    "fmt"
)

func main() {
    fmt.Println(fmt.Sprint(421.034))

    f := 5524.53
    fmt.Println(fmt.Sprint(f))
}
Output421.034
5524.53

Вы можете проверить, чтобы убедиться, что это правильно, связав строку:

package main

import (
    "fmt"
)

func main() {
    f := 5524.53
    fmt.Println("Sammy has " + fmt.Sprint(f) + " points.")
}
OutputSammy has 5524.53 points.

Вы можете быть уверены, что ваш float был правильно преобразован в строку, потому что конкатенация была выполнена без ошибок.

Преобразование строк в числа

Строки можно преобразовать в числа с помощью пакетаstrconv в стандартной библиотеке Go. В пакетеstrconv есть функции для преобразования целочисленных и числовых типов. Это очень распространенная операция при приеме ввода от пользователя. Например, если у вас есть программа, которая запрашивает возраст человека, когда они вводят ответ, он фиксируется какstring. Затем вам нужно будет преобразовать его вint, чтобы делать с ним какие-либо математические вычисления.

Если в вашей строке нет десятичных знаков, вы, скорее всего, захотите преобразовать ее в целое число с помощью функцииstrconv.Atoi. Если вы знаете, что будете использовать число как число с плавающей запятой, вы должны использоватьstrconv.ParseFloat.

Давайте используем пример того, как пользователь Sammy отслеживает строки кода, написанные каждый день. Возможно, вы захотите манипулировать этими значениями с помощью математики, чтобы обеспечить более интересную обратную связь для пользователя, но эти значения в настоящее время хранятся в строках:

package main

import (
    "fmt"
)

func main() {
    lines_yesterday := "50"
    lines_today := "108"

    lines_more := lines_today - lines_yesterday

    fmt.Println(lines_more)
}
Outputinvalid operation: lines_today - lines_yesterday (operator - not defined on string)

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

Измените код, включив методstrconv.Atoi(), который преобразует строки в целые числа, что позволит вам выполнять математические вычисления со значениями, которые изначально были строками. Поскольку существует вероятность сбоя при преобразовании строки в целое число, вы должны проверить наличие ошибок. Вы можете использовать операторif, чтобы проверить, было ли преобразование успешным.

package main

import (
    "fmt"
    "log"
    "strconv"
)

func main() {
    lines_yesterday := "50"
    lines_today := "108"

    yesterday, err := strconv.Atoi(lines_yesterday)
    if err != nil {
        log.Fatal(err)
    }

    today, err := strconv.Atoi(lines_today)
    if err != nil {
        log.Fatal(err)
    }
    lines_more := today - yesterday

    fmt.Println(lines_more)
}

Поскольку строка может не быть числом, методstrconv.Atoi() вернет как преобразованный тип, так и потенциальную ошибку. При преобразовании изlines_yesterday с помощью функцииstrconv.Atoi вы должны проверить возвращаемое значениеerr, чтобы убедиться, что значение было преобразовано. Еслиerr неnil, это означает, чтоstrconv.Atoi не удалось успешно преобразовать строковое значение в целое число. В этом примере вы использовали операторif для проверки наличия ошибки, а если ошибка была возвращена, вы использовалиlog.Fatal для регистрации ошибки и выхода из программы.

Когда вы запустите предыдущий код, вы получите:

Output58

Теперь попробуйте преобразовать строку, которая не является числом:

package main

import (
    "fmt"
    "strconv"
)

func main() {
    a := "not a number"
    b, err := strconv.Atoi(a)
    fmt.Println(b)
    fmt.Println(err)
}

Вы получите следующую ошибку:

Output0
strconv.Atoi: parsing "not a number": invalid syntax

Посколькуb был объявлен, ноstrconv.Atoi не удалось выполнить преобразование, значение никогда не было присвоеноb. Обратите внимание, чтоb имеет значение0. Это потому, что Go имеет значения по умолчанию, называемые нулевыми значениями в Go. strconv.Atoi выдает ошибку, описывающую, почему не удалось преобразовать строку.

Преобразование строк и байтов

Строки в Go хранятся в виде фрагмента байтов. В Go вы можете преобразовать фрагмент байтов в строку, заключив его в соответствующие преобразования[]byte() иstring():

package main

import (
    "fmt"
)

func main() {
    a := "my string"

    b := []byte(a)

    c := string(b)

    fmt.Println(a)

    fmt.Println(b)

    fmt.Println(c)
}

Здесь вы сохранили строковое значение вa, затем преобразовали его в фрагмент байтовb, а затем преобразовали этот фрагмент байтов обратно в строку какc. Затем вы выводите на экранa,b иc:

Outputmy string
[109 121 32 115 116 114 105 110 103]
my string

Первая строка вывода - это исходная строкаmy string. Вторая распечатанная строка - это фрагмент байта, который составляет исходную строку. Третья строка показывает, что фрагмент байта можно безопасно преобразовать обратно в строку и распечатать обратно.

Заключение

В этом руководстве показано, как преобразовать несколько важных собственных типов данных в другие типы данных, в основном с помощью встроенных методов. Возможность конвертировать типы данных в Go позволит вам делать такие вещи, как принимать пользовательский ввод и выполнять математические операции для разных типов чисел. Позже, когда вы будете использовать Go для написания программ, которые принимают данные из множества различных источников, таких как базы данных и API, вы будете использовать эти методы преобразования, чтобы убедиться, что вы можете действовать в отношении ваших данных. Вы также сможете оптимизировать хранение путем преобразования данных в меньшие типы данных.

Если вам нужен более глубокий анализ типов данных в Go, ознакомьтесь с нашей статьейUnderstanding Data Types in Go.