360просмотров
16 августа 2025 г.
Score: 396
Приведение byte в виде цифры к int в Golang Регулярно я решаю различные задачи на Leetcode уже второй год подряд(кстати планирую написать большую статью к концу года - как я решил 1000 задач) - я сталкиваюсь с различными нюансами в языках программирования. Сегодня поговорим об одном таком нюансе в Golang.
Задача: мы хотим из строки "извлекать" цифры и приводить их к типу int. В Php все проще, есть строка и eсли нам надо "вытащить" цифру из этой строки это сделать довольно-таки просто. $example = '123'; $castToIntFirst = (int)$example[0];
$castToIntSec = (int)$example[0]; echo gettype($castToIntFirst) . PHP_EOL;
echo gettype($castToIntSec) . PHP_EOL; echo $castToIntFirst + $castToIntSec;
// integer integer 2 Мы опускаем мультибайтовые строки для упрощения - представим что в строке у нас все в ASCII Но в Go все не так просто - так как string это одно - а часть этого string это другое.
На самом деле проще говоря - строка в Go - это slice байтов.
Так как мы хотим "вытащить" цифру из строки - задача трансформируется в -> привести byte к int, так как один byte это одна цифра. Но я вам хочу показать одну хитрость, которую я делал не только в Go.
Так как мы условились что исходная строка у нас в ASCII - то мы можем взять каждый байт из этой строки по отдельности.
Каждый байт в такой строке будет представлен в виде ASCII кода - и мы можем например посмотреть этот ASCII код в десятичной сис-ме как в примере ниже. func main() { example := "123" first := example[0] sec := example[1] fmt.Printf("%v\n", first) // in decimal 49 fmt.Printf("%v\n", sec) // in decimal 50
} То есть у нас есть байт. Байт представен как ASCII код - а для человека визуально это просто цифра в десятичной сис-ме - которую мы и хотим в конце концов как int! Для это используем трюк вычитания. Цифра '0' в ASCII представлена как 48 в десятичной сис-ме. Если мы возьмем ASCII код любой цифры от нуля до 9 - мы получим число от 48 до 57. Далее вычитаем ASCII код '0'-ля из байта который нам нужен и получаем разницу в виде той цифры - которую мы пытались получить. Например 👇 func main() { example := "123" diff := example[0] - '0' // uint8(1) - rune(0) or 49 - 48 fmt.Printf("%v\n", diff) // 1
} Тут стоит обратить внимание, что '0' имеет тип rune. При арифметических операциях - Golang понимает что надо сделать и приводит наш rune к byte. Это кстати не всегда возможно, так как вот такая руна - 'б' уже не ASCII код и в один байт не помешается - поэтому мы получим ошибку переполнения. Напоследок осталось привести число до типа int - так как ответ наш будет байтом или uint8 - мы должны его привести к int и вся эта операция безоспасна т.к. мы "расширяем" uint8 до типа int.
А любое значение в 1 байте легко помещается в int func main() { example := "123" diff := int(example[0] - '0') // uint8(1) - rune(0) fmt.Printf("%T\n", diff) // int
} Вот такой вот трюк. Признаться на сколько он полезен в реальной жизни не знаю - задача извлекать цифры из строк не особо популярная - но мне нравиться как знания о кодировках и простая арифметика помогают решать такие задачи.