Строки в Go — это иммутабельные массивы байт. Для стандартного компилятора Go внутренняя структура строки описана как:
type _string struct {
elements *byte // байты
len int // кол-во байт
}
После инициализации строку нельзя изменить и такая иммутабельность позволяет избежать побочных эффектов в коде.
s := "hello"
s[4] = "" // ошибка компиляции: cannot assign to s[4] (strings are immutable)
Стоит отметить, что тип данных byte
— это алиас к типу uint8
(0-255). Во-первых, потому что нужно абстрактно отличать типы в коде. Во-вторых, байты представляют ASCII символы, а в кодовой таблице ASCII символов 256 кодов:
package main
import "fmt"
func main() {
s := "hey"
fmt.Println(s[0], s[1], s[2]) // 104 101 121
fmt.Println(string(s[0]), string(s[1]), string(s[2])) // h e y
}
Большинство библиотечных функций работают со слайсами байт []byte
для производительности. Конвертация строки в слайс байт описывается в коде явно:
package main
import "fmt"
func main() {
s := "hey"
bs := []byte(s)
fmt.Println([]byte(s)) // [104 101 121]
fmt.Println(string(bs)) // hey
}
Отдельные ASCII символы можно объявлять сразу с типом byte
. Для этого нужно обернуть символ в одинарные кавычки и указать тип byte
:
package main
import (
"fmt"
"reflect"
)
func main() {
asciiCh := byte('Z')
asciiChStr := string(asciiCh)
fmt.Println(reflect.TypeOf(asciiCh), asciiCh) // uint8 90
fmt.Println(reflect.TypeOf(asciiChStr), asciiChStr) // string Z
}
Реализуйте функции nextASCII(b byte) byte
и prevASCII(b byte) byte
, которые возвращают следующий или предыдущий символ ASCII таблицы соответственно. Например:
string(nextASCII(byte('a'))) // 'b'
string(prevASCII(byte('b'))) // 'a'
Допускаем, что в функцию prevASCII
не может прийти нулевой символ, а в функцию nextASCII
— последний символ ASCII таблицы.
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Ваше упражнение проверяется по этим тестам
1package solution
2
3import (
4 "github.com/stretchr/testify/assert"
5 "testing"
6)
7
8func TestNextASCII(t *testing.T) {
9 a := assert.New(t)
10 a.Equal(byte('b'), nextASCII(byte('a')))
11 a.Equal(byte('y'), nextASCII(byte('x')))
12 a.Equal(byte('6'), nextASCII(byte('5')))
13}
14
15func TestPrevASCII(t *testing.T) {
16 a := assert.New(t)
17 a.Equal(byte('7'), prevASCII(byte('8')))
18 a.Equal(byte('c'), prevASCII(byte('d')))
19 a.Equal(byte('m'), prevASCII(byte('n')))
20}
21
Решение учителя откроется через: