NOTE

1.6 string

Character sets and Unicode, basic Go string usage, string/[]byte conversion, StringHeader, and string immutability.

GoCreated Updated 1 min readhistorical

This is a historical learning note and may contain outdated or incomplete understanding.

1. Character Sets

A computer can only store bytes (binary), so characters must also be stored using bytes. But how are they displayed after being stored? A mapping between bytes and characters is needed. This is a character set. For example:

1.1. Unicode Character Set

  • Origin At first there was only the ASCII character set, which only supported English; GB2312 was introduced to support Simplified Chinese; BIG5 was introduced to support Traditional Chinese… There were too many standards and no unification, so Unicode appeared.
  • Fixed-length encoding
  • Variable-length encoding
    • UTF-8 character set

2. What It Is

  • A string encoded using Unicode.

3. Usage

3.1. Basic Usage

func TestString1(t *testing.T) {
	s := "hello world"
	fmt.Println(s, len(s))

	s1 := s + "!"
	fmt.Println(s1, len(s1))

	s2 := s[:5]
	fmt.Println(s2, len(s2))

	for _, i := range s2 {
		fmt.Println(i, string(i))
	}

}

// output
hello world 11
hello world! 12
hello 5
104 h
101 e
108 l
108 l
111 o

3.2. Conversion Between string and []byte

  • string to []byte
func str2bytes(s string) []byte {
	p := make([]byte, len(s))
	for i := 0; i < len(s); i++ {
		c := s[i]
		p[i] = c
	}
	return p
}

func TestString2(t *testing.T) {
	fmt.Println(str2bytes("hello"))
}

// output
[104 101 108 108 111]
  • []byte to string
func TestString3(t *testing.T) {
	fmt.Println(bytes2str([]byte{104, 101, 108, 108, 111}))
}

func bytes2str(s []byte) (p string) {
	data := make([]byte, len(s))
	for i, c := range s {
		data[i] = c
	}

	hdr := (*reflect.StringHeader)(unsafe.Pointer(&p))
	hdr.Data = uintptr(unsafe.Pointer(&data[0]))
	hdr.Len = len(s)

	return p
}
// output
hello

4. Implementation

4.1. Data Structure

type StringHeader struct {
    Data uintptr// the underlying byte array pointed to by the string
    Len  int// length of the string in bytes
}

4.1.1. How the End of a Character Sequence Is Determined

  • C uses '\0' to determine the character boundary, while Golang uses a length field.

4.1.2. The Underlying Storage Is an Immutable Byte Array

s := "test"
fmt.Println(s[1])
s[1] = 'c'// does not compile

4.1.2.1. Why It Is Immutable
s := "test"
s1 := s[1:]
  • If s1 could be modified, it would affect s, which could cause unpredictable consequences.

5. References

Discussion

Sign in with GitHub to comment. Discussions are stored as GitHub Issues.View on GitHub