Преобразование типов и strconv
Go не делает неявных преобразований. Если нужно из string получить int - нужно сказать это явно. Это защищает от багов, но нужно знать как. Основы про типы - в уроке Переменные и типы без паники.
Преобразование между числовыми типами
var x int = 42
var y float64 = float64(x) // int → float64
var z int32 = int32(x) // int → int32
// Потеря данных при сужении типа!
var big int64 = 1_000_000
var small int8 = int8(big) // overflow: -64
Строка ↔ Число: пакет strconv
Это главный пакет для преобразования строк в числа и обратно.
Строка → Число
import "strconv"
// Строка → int
num, err := strconv.Atoi("42")
if err != nil {
fmt.Println("Ошибка:", err)
}
fmt.Println(num) // 42
// Строка → int64 (с указанием основания и разрядности)
num64, err := strconv.ParseInt("FF", 16, 64)
fmt.Println(num64) // 255
// Строка → float64
price, err := strconv.ParseFloat("99.99", 64)
fmt.Println(price) // 99.99
// Строка → bool
flag, err := strconv.ParseBool("true")
fmt.Println(flag) // true
Число → Строка
// int → строка
s := strconv.Itoa(42)
fmt.Println(s) // "42"
// float → строка
s2 := strconv.FormatFloat(3.14159, 'f', 2, 64)
fmt.Println(s2) // "3.14"
// Через fmt.Sprintf (универсальный способ)
s3 := fmt.Sprintf("%d", 42)
s4 := fmt.Sprintf("%.2f", 3.14)
s5 := fmt.Sprintf("%t", true)
<ComparisonTable data={{ headers: ["Задача", "Функция", "Пример"], rows: [ ["string → int", "strconv.Atoi", "Atoi("42") → 42"], ["int → string", "strconv.Itoa", "Itoa(42) → "42""], ["string → float64", "strconv.ParseFloat", "ParseFloat("3.14", 64) → 3.14"], ["string → int64", "strconv.ParseInt", "ParseInt("FF", 16, 64) → 255"], ["string → bool", "strconv.ParseBool", "ParseBool("true") → true"], ["любой → string", "fmt.Sprintf", "Sprintf("%d", 42) → "42""] ] }} />
Обработка ошибок преобразования
Преобразование может не удаться - всегда проверяй error (подробнее - в уроке Обработка ошибок):
inputs := []string{"42", "hello", "3.14", "", "-7"}
for _, s := range inputs {
num, err := strconv.Atoi(s)
if err != nil {
fmt.Printf(" %q - ошибка: %v\n", s, err)
} else {
fmt.Printf(" %q → %d\n", s, num)
}
}
// "42" → 42
// "hello" - ошибка: strconv.Atoi: parsing "hello": invalid syntax
// "3.14" - ошибка: strconv.Atoi: parsing "3.14": invalid syntax
// "" - ошибка: strconv.Atoi: parsing "": invalid syntax
// "-7" → -7
Строка ↔ Байты
// string → []byte
s := "Привет"
b := []byte(s)
fmt.Println(b) // [208 159 209 ...]
// []byte → string
s2 := string(b)
fmt.Println(s2) // Привет
// int → rune → string
r := rune(65)
fmt.Println(string(r)) // A
Практический пример: парсинг конфига
func parseConfig(lines []string) map[string]interface{} {
config := make(map[string]interface{})
for _, line := range lines {
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
continue
}
key := strings.TrimSpace(parts[0])
val := strings.TrimSpace(parts[1])
// Пробуем разные типы
if i, err := strconv.Atoi(val); err == nil {
config[key] = i
} else if f, err := strconv.ParseFloat(val, 64); err == nil {
config[key] = f
} else if b, err := strconv.ParseBool(val); err == nil {
config[key] = b
} else {
config[key] = val // оставляем как строку
}
}
return config
}
// port=8080 → int 8080
// rate=0.5 → float64 0.5
// debug=true → bool true
// host=localhost → string "localhost"
Типичные ошибки
// ОШИБКА: string(число) - это не то, что ты думаешь!
fmt.Println(string(65)) // "A" (Unicode символ), НЕ "65"!
fmt.Println(strconv.Itoa(65)) // "65" - правильно
// ОШИБКА: забыть проверить err
num, _ := strconv.Atoi(userInput) // если "abc" → num будет 0 без ошибки!