Поговорим о представлении символов и обходе строк в языке Go.

Go
Поговорим о представлении символов и обходе строк в языке Go.

В отличие от других языков, в Go нет типов символов,Символы — это всего лишь частный случай целых чисел..

зачем говоритьСимволы — это всего лишь частный случай целых чисел.Шерстяная ткань? Поскольку в Gobyteиruneтипыпсевдоним для целого числа. В исходном коде Go мы видим:

// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8

// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32
  • byteдаuint8псевдоним длиной 1 байт, используемый для представления символов ASCII
  • runeдаint32Псевдоним длиной 4 байта для представления кодовой точки Unicode, закодированной в UTF-8.

Советы: Unicode начинается с 0 и присваивает номер каждому символу, который называется «кодовой точкой».

представление персонажей

Итак, как представлять символы в языке Go?

Использование в Goв одинарных кавычкахдля представления символов, таких как'j'.

byte

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

var byteC byte = 'j'

Также из-заbyteЦелое числоuint8, поэтому его можно напрямую преобразовать в целочисленное значение. В спецификаторе формата мы используем%cпредставляет характер,%dПредставляет целое число:

// 声明 byte 类型字符
var byteC byte = 'j'
fmt.Printf("字符 %c 对应的整型为 %d\n", byteC, byteC)
// Output: 字符 j 对应的整型为 106

rune

иbyteто же самое, хочу объявитьruneможно использовать тип символовruneКлючевое слово указывает:

var runeC rune = 'J'

Но если вы не укажете тип при объявлении символьной переменной, Go по умолчанию установит его равнымruneтип:

runeC := 'J'
fmt.Printf("字符 %c 的类型为 %T\n", runeC, runeC)
// Output: 字符 J 的类型为 int32

Зачем нужны два типа?

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

мы знаем,byteЗанимает один байт, поэтому его можно использовать для представления символов ASCII.UTF-8 — это метод кодирования переменной длины с длиной символов от 1 до 4 байтов..byteЯвно плохо разбираюсь в таких представлениях, даже если вы хотите использовать несколькоbyteЧтобы представить это, у вас нет возможности узнать, сколько байтов символов UTF-8 вы имеете дело.

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

testString := "你好,世界"
fmt.Println(testString[:2]) // 输出乱码,因为截取了前两个字节
fmt.Println(testString[:3]) // 输出「你」,一个中文字符由三个字节表示

В это время необходимоruneпомощь. использовать[]rune()Преобразуйте строку в кодовые точки Unicode, а затем усеките, чтобы вам не нужно было рассматривать случай, когда строка содержит символы UTF-8:

testString := "你好,世界"
fmt.Println(string([]rune(testString)[:2])) // 输出:「你好」

Советы: Unicode, как и ASCII, — это набор символов, а UTF-8 — это метод кодирования.

перебирать строку

Существует два способа обхода строк: один — обход индекса, а другой — использованиеrange.

обход нижнего индекса

Поскольку в языке Go строки хранятся в кодировке UTF-8, используйтеlen()Когда функция получает длину строки, она получает длину строки в кодировке UTF-8 в байтах.Индексация строки по нижнему индексу даст байт. Поэтому, если строка содержит символы в кодировке UTF-8, она будет отображаться искаженной:

testString := "Hello,世界"

for i := 0; i < len(testString); i++ {
	c := testString[i]
	fmt.Printf("%c 的类型是 %s\n", c, reflect.TypeOf(c))
}

/* Output:
H 的类型是 uint8(ASCII 字符返回正常)
e 的类型是 uint8
l 的类型是 uint8
l 的类型是 uint8
o 的类型是 uint8
ï 的类型是 uint8(从这里开始出现了奇怪的乱码)
¼ 的类型是 uint8
Œ 的类型是 uint8
ä 的类型是 uint8
¸ 的类型是 uint8
– 的类型是 uint8
ç 的类型是 uint8
• 的类型是 uint8
Œ 的类型是 uint8
*/

range

rangeпересечение получитruneТип персонажей:

testString := "Hello,世界"

for _, c := range testString {
	fmt.Printf("%c 的类型是 %s\n", c, reflect.TypeOf(c))
}

/* Output:
H 的类型是 int32
e 的类型是 int32
l 的类型是 int32
l 的类型是 int32
o 的类型是 int32
, 的类型是 int32
世 的类型是 int32
界 的类型是 int32
*/

Суммировать

  • В языке Go нет концепции символов,Символ — это набор байтов, который может быть одним байтом (набор символов ASCII) или несколькими байтами (набор символов Unicode).
  • byteдаuint8псевдоним длиной 1 байт, используемый для представления символов ASCII
  • runeявляетсяint32Псевдоним длиной 4 байта для представления кодовой точки Unicode, закодированной в UTF-8.
  • Усечение строки в байтах
  • Использование индексов для индексации строки дает байты
  • хочу пересечьruneиспользуются символы типаrangeметод прохождения

использованная литература

Связанное Чтение


Если вы считаете, что статья написана хорошо, пожалуйста, сделайте мне две маленькие одолжения:

  1. Ставьте лайк и подписывайтесь на меня, пусть эту статью увидит больше людей
  2. Обратите внимание на общественный номер»программирование для спасения мира», вы получите толчок новых статей как можно скорее

Ваша поддержка - самая большая мотивация для моего творчества, спасибо всем!