Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

unicode/utf16 包详解

概述

unicode/utf16 包实现了 UTF-16 序列的编码和解码功能。

主要用途

  • UTF-16 编码和解码
  • rune 与 UTF-16 码元序列转换
  • 代理对(surrogate pair)处理
  • 与 Windows API 交互
  • 处理 Java/.NET 字符串

核心概念

  • UTF-16:16 位 Unicode 编码格式
  • rune:Go 中的 Unicode 码点类型(int32 的别名)
  • 代理对:用于编码 U+10000 以上码点的两个 16 位码元
  • 高代理(High Surrogate):U+D800 到 U+DBFF
  • 低代理(Low Surrogate):U+DC00 到 U+DFFF

Go 版本要求:所有 Go 版本

包导入

import "unicode/utf16"

函数详解(按 A-Z 分层归类)

A

AppendRune

func AppendRune(a []uint16, r rune) []uint16

作用:将 Unicode 码点 r 的 UTF-16 编码追加到 p 的末尾并返回扩展后的缓冲区

参数说明

  • a:目标 uint16 切片
  • r:要编码的 Unicode 码点

返回值

  • 扩展后的 uint16 切片

说明

  • 如果 rune 不是有效的 Unicode 码点,会追加 U+FFFD 的编码
  • 对于 U+10000 以上的码点,会使用代理对(2 个 uint16)
  • 对于不需要代理对的码点,只使用 1 个 uint16

示例

// 追加基本多文种平面(BMP)内的字符
a := []uint16{}
a = utf16.AppendRune(a, 'A')
a = utf16.AppendRune(a, '中')
fmt.Printf("%v\n", a)
// 输出:[65 20013]

// 追加需要代理对的字符(emoji)
a = []uint16{}
a = utf16.AppendRune(a, '😀')  // U+1F600
fmt.Printf("%v\n", a)
// 输出:[55357 56832] (代理对)

// 追加无效码点
a = utf16.AppendRune(a, unicode/utf8.MaxRune+1)
fmt.Printf("%v\n", a)
// 输出:[55357 56832 65533] (65533 是 U+FFFD)

// 批量追加
runes := []rune{'H', 'e', 'l', 'l', 'o'}
var buf []uint16
for _, r := range runes {
    buf = utf16.AppendRune(buf, r)
}
fmt.Printf("%v\n", buf)
// 输出:[72 101 108 108 111]

D

Decode

func Decode(s []uint16) []rune

作用:返回 UTF-16 编码 s 表示的 Unicode 码点序列

参数说明

  • s:UTF-16 编码的 uint16 切片

返回值

  • 解码后的 rune 切片

说明

  • 自动处理代理对
  • 无效的代理对会被替换为 U+FFFD

示例

// 解码 BMP 字符
s := []uint16{72, 101, 108, 108, 111}  // "Hello"
runes := utf16.Decode(s)
fmt.Println(string(runes))
// 输出:Hello

// 解码包含代理对的字符串
s = []uint16{20013, 25991}  // "中文"
runes = utf16.Decode(s)
fmt.Println(string(runes))
// 输出:中文

// 解码 emoji(代理对)
s = []uint16{55357, 56832}  // 😀 的代理对
runes = utf16.Decode(s)
fmt.Printf("%c\n", runes[0])
// 输出:😀

// 解码混合内容
s = []uint16{72, 105, 20013, 55357, 56832}  // "Hi 中😀"
runes = utf16.Decode(s)
fmt.Println(string(runes))
// 输出:Hi 中😀

// 无效代理对的处理
s = []uint16{55357}  // 只有高代理,不完整
runes = utf16.Decode(s)
fmt.Printf("%c\n", runes[0])
// 输出: (U+FFFD)

DecodeRune

func DecodeRune(r1, r2 rune) rune

作用:返回代理对的 UTF-16 解码

参数说明

  • r1:高代理(high surrogate)
  • r2:低代理(low surrogate)

返回值

  • 解码后的 Unicode 码点
  • 如果代理对无效,返回 U+FFFD

说明

  • r1 应该在 U+D800 到 U+DBFF 范围内
  • r2 应该在 U+DC00 到 U+DFFF 范围内
  • 如果不符合上述范围,返回 U+FFFD

示例

// 解码有效的代理对
r1 := rune(0xD83D)  // 高代理
r2 := rune(0xDE00)  // 低代理
decoded := utf16.DecodeRune(r1, r2)
fmt.Printf("%c (U+%04X)\n", decoded, decoded)
// 输出:😀 (U+1F600)

// 解码无效的代理对
r1 = 0xD800  // 高代理
r2 = 0xD800  // 应该是低代理,但这是高代理
decoded = utf16.DecodeRune(r1, r2)
fmt.Printf("%c (U+%04X)\n", decoded, decoded)
// 输出: (U+FFFD)

// 单个有效值(不是代理对)
decoded = utf16.DecodeRune('A', 'B')
fmt.Printf("%c\n", decoded)
// 输出: (U+FFFD)

E

Encode

func Encode(s []rune) []uint16

作用:返回 Unicode 码点序列 s 的 UTF-16 编码

参数说明

  • s:rune 切片

返回值

  • UTF-16 编码的 uint16 切片

说明

  • 对于 U+10000 以上的码点,会使用代理对
  • 对于 BMP 内的码点,直接编码为单个 uint16

示例

// 编码 BMP 字符
runes := []rune{'H', 'e', 'l', 'l', 'o'}
encoded := utf16.Encode(runes)
fmt.Printf("%v\n", encoded)
// 输出:[72 101 108 108 111]

// 编码中文字符
runes = []rune{'中', '文'}
encoded = utf16.Encode(runes)
fmt.Printf("%v\n", encoded)
// 输出:[20013 25991]

// 编码 emoji(需要代理对)
runes = []rune{'😀', '😃', '😄'}
encoded = utf16.Encode(runes)
fmt.Printf("%v\n", encoded)
fmt.Printf("Length: %d\n", len(encoded))
// 输出:[55357 56832 55357 56835 55357 56836]
// Length: 6 (每个 emoji 使用 2 个 uint16)

// 编码混合内容
runes = []rune{'A', '中', '😀'}
encoded = utf16.Encode(runes)
fmt.Printf("%v\n", encoded)
// 输出:[65 20013 55357 56832]

EncodeRune

func EncodeRune(r rune) (r1, r2 rune)

作用:返回给定 rune 的 UTF-16 代理对 r1, r2

参数说明

  • r:要编码的 Unicode 码点

返回值

  • r1:高代理(high surrogate)
  • r2:低代理(low surrogate)
  • 如果 rune 不是有效的 Unicode 码点或不需要编码,返回 (U+FFFD, U+FFFD)

说明

  • 只有 U+10000 到 U+10FFFF 范围内的码点需要代理对
  • BMP 内的码点(U+0000 到 U+FFFF)不需要代理对
  • 无效的码点(超出范围或代理对本身)返回 (U+FFFD, U+FFFD)

示例

// 编码需要代理对的字符
r1, r2 := utf16.EncodeRune('😀')  // U+1F600
fmt.Printf("r1=U+%04X, r2=U+%04X\n", r1, r2)
// 输出:r1=U+D83D, r2=U+DE00

// 验证解码
decoded := utf16.DecodeRune(r1, r2)
fmt.Printf("Decoded: %c\n", decoded)
// 输出:Decoded: 😀

// 编码 BMP 字符(不需要代理对)
r1, r2 = utf16.EncodeRune('A')
fmt.Printf("r1=U+%04X, r2=U+%04X\n", r1, r2)
// 输出:r1=U+FFFD, r2=U+FFFD (表示不需要代理对)

// 编码无效码点
r1, r2 = utf16.EncodeRune(unicode/utf8.MaxRune + 1)
fmt.Printf("r1=U+%04X, r2=U+%04X\n", r1, r2)
// 输出:r1=U+FFFD, r2=U+FFFD

// 编码代理对本身(无效)
r1, r2 = utf16.EncodeRune(0xD800)
fmt.Printf("r1=U+%04X, r2=U+%04X\n", r1, r2)
// 输出:r1=U+FFFD, r2=U+FFFD

I

IsSurrogate

func IsSurrogate(r rune) bool

作用:报告指定的 Unicode 码点是否可以出现在代理对中

参数说明

  • r:要检查的 Unicode 码点

返回值

  • 如果是高代理或低代理返回 true,否则返回 false

说明

  • 高代理范围:U+D800 到 U+DBFF
  • 低代理范围:U+DC00 到 U+DFFF
  • 代理对本身不能单独出现在有效的 Unicode 文本中

示例

// 检查高代理
fmt.Println(utf16.IsSurrogate(0xD800))
// 输出:true
fmt.Println(utf16.IsSurrogate(0xDBFF))
// 输出:true

// 检查低代理
fmt.Println(utf16.IsSurrogate(0xDC00))
// 输出:true
fmt.Println(utf16.IsSurrogate(0xDFFF))
// 输出:true

// 检查非代理字符
fmt.Println(utf16.IsSurrogate('A'))
// 输出:false
fmt.Println(utf16.IsSurrogate('中'))
// 输出:false
fmt.Println(utf16.IsSurrogate('😀'))
// 输出:false

// 检查边界值
fmt.Println(utf16.IsSurrogate(0xD7FF))  // 代理对之前
// 输出:false
fmt.Println(utf16.IsSurrogate(0xE000))  // 代理对之后
// 输出:false

R

RuneLen

func RuneLen(r rune) int

作用:返回 rune 的 UTF-16 编码中的 16 位码元数量

参数说明

  • r:要计算的 Unicode 码点

返回值

  • 码元数量(1 或 2)
  • 如果 rune 不是有效的 UTF-16 编码值,返回 -1

说明

  • BMP 内的码点(U+0000 到 U+FFFF):1 个码元
  • 辅助平面码点(U+10000 到 U+10FFFF):2 个码元(代理对)
  • 无效的码点(超出范围或代理对本身):-1

示例

// ASCII 字符
fmt.Println(utf16.RuneLen('A'))
// 输出:1

// 中文字符(BMP 内)
fmt.Println(utf16.RuneLen('中'))
// 输出:1

// emoji(需要代理对)
fmt.Println(utf16.RuneLen('😀'))
// 输出:2

// 辅助平面字符
fmt.Println(utf16.RuneLen('𐀀'))  // U+10000
// 输出:2

// 无效码点
fmt.Println(utf16.RuneLen(unicode/utf8.MaxRune + 1))
// 输出:-1

// 代理对本身
fmt.Println(utf16.RuneLen(0xD800))
// 输出:-1

类型详解

unicode/utf16 包不导出任何类型,所有功能通过函数提供。

典型示例

1. 基本编码和解码

package main

import (
    "fmt"
    "unicode/utf16"
)

func main() {
    // 原始字符串
    str := "Hello, 世界!😀"
    
    // 转换为 rune 切片
    runes := []rune(str)
    
    // 编码为 UTF-16
    encoded := utf16.Encode(runes)
    fmt.Printf("UTF-16: %v\n", encoded)
    
    // 解码回 rune
    decoded := utf16.Decode(encoded)
    fmt.Printf("Decoded: %s\n", string(decoded))
    
    // 验证
    fmt.Printf("Match: %v\n", string(runes) == string(decoded))
}

2. 处理代理对

package main

import (
    "fmt"
    "unicode/utf16"
)

func main() {
    // emoji 需要代理对
    emoji := '😀'  // U+1F600
    
    // 编码为代理对
    r1, r2 := utf16.EncodeRune(emoji)
    fmt.Printf("High surrogate: U+%04X\n", r1)
    fmt.Printf("Low surrogate: U+%04X\n", r2)
    
    // 解码代理对
    decoded := utf16.DecodeRune(r1, r2)
    fmt.Printf("Decoded: %c (U+%04X)\n", decoded, decoded)
    
    // 检查长度
    fmt.Printf("UTF-16 length: %d\n", utf16.RuneLen(emoji))
    
    // 验证代理
    fmt.Printf("Is r1 surrogate: %v\n", utf16.IsSurrogate(r1))
    fmt.Printf("Is r2 surrogate: %v\n", utf16.IsSurrogate(r2))
}

3. 使用 AppendRune 构建 UTF-16 序列

package main

import (
    "fmt"
    "unicode/utf16"
)

func main() {
    // 构建 UTF-16 序列
    var buf []uint16
    
    text := []rune("Hello 世界 😀")
    for _, r := range text {
        buf = utf16.AppendRune(buf, r)
    }
    
    fmt.Printf("UTF-16: %v\n", buf)
    fmt.Printf("Length: %d uint16s\n", len(buf))
    
    // 解码验证
    decoded := utf16.Decode(buf)
    fmt.Printf("Decoded: %s\n", string(decoded))
}

4. 计算 UTF-16 长度

package main

import (
    "fmt"
    "unicode/utf16"
)

func main() {
    texts := []string{
        "Hello",
        "世界",
        "😀😃😄",
        "Hello 世界 😀",
    }
    
    for _, text := range texts {
        runes := []rune(text)
        
        // 计算 UTF-16 长度
        var utf16Len int
        for _, r := range runes {
            utf16Len += utf16.RuneLen(r)
        }
        
        fmt.Printf("%q:\n", text)
        fmt.Printf("  Runes: %d\n", len(runes))
        fmt.Printf("  UTF-16 length: %d\n", utf16Len)
        fmt.Printf("  UTF-8 length: %d\n", len(text))
        fmt.Println()
    }
}

5. 与 Windows API 交互

package main

import (
    "fmt"
    "unicode/utf16"
)

// 模拟 Windows API 调用
func windowsAPIExample() {
    // Go 字符串
    goStr := "Hello, 世界!"
    
    // 转换为 UTF-16(Windows 使用 UTF-16)
    runes := []rune(goStr)
    utf16Str := utf16.Encode(runes)
    
    fmt.Printf("Go string: %s\n", goStr)
    fmt.Printf("UTF-16: %v\n", utf16Str)
    fmt.Printf("UTF-16 length: %d\n", len(utf16Str))
    
    // 添加 NUL 终止符(Windows API 需要)
    utf16Str = append(utf16Str, 0)
    
    // 模拟从 Windows API 返回 UTF-16 字符串
    returnedUTF16 := utf16Str[:len(utf16Str)-1]  // 移除 NUL
    
    // 转换回 Go 字符串
    returnedRunes := utf16.Decode(returnedUTF16)
    returnedStr := string(returnedRunes)
    
    fmt.Printf("Returned: %s\n", returnedStr)
}

func main() {
    windowsAPIExample()
}

6. 处理无效输入

package main

import (
    "fmt"
    "unicode/utf16"
)

func main() {
    // 无效的代理对序列
    invalid := []uint16{0xD800}  // 只有高代理
    decoded := utf16.Decode(invalid)
    fmt.Printf("Invalid high surrogate: %c (U+%04X)\n", decoded[0], decoded[0])
    
    // 错误的代理对顺序
    invalid = []uint16{0xDC00, 0xD800}  // 低代理在前
    decoded = utf16.Decode(invalid)
    fmt.Printf("Wrong order: %c %c\n", decoded[0], decoded[1])
    
    // 无效的码点
    fmt.Println(utf16.RuneLen(0x110000))  // 超出范围
    // 输出:-1
    
    // 代理对本身
    fmt.Println(utf16.IsSurrogate(0xD800))  // 高代理
    // 输出:true
    fmt.Println(utf16.IsSurrogate(0xDC00))  // 低代理
    // 输出:true
}

7. 比较 UTF-8 和 UTF-16

package main

import (
    "fmt"
    "unicode/utf8"
    "unicode/utf16"
)

func main() {
    texts := []rune{
        'A',       // ASCII
        'é',       // Latin-1
        '中',       // CJK
        '😀',       // Emoji
        '𐀀',       // Supplementary
    }
    
    fmt.Printf("%-10s %-10s %-10s %-10s\n", "Rune", "UTF-8", "UTF-16", "Name")
    fmt.Println(strings.Repeat("-", 50))
    
    for _, r := range texts {
        utf8Len := utf8.RuneLen(r)
        utf16Len := utf16.RuneLen(r)
        
        fmt.Printf("%-10c %-10d %-10d %-10s\n", 
            r, utf8Len, utf16Len, fmt.Sprintf("U+%04X", r))
    }
}

8. 字符串转换工具

package main

import (
    "fmt"
    "unicode/utf16"
)

// StringToUTF16 将 Go 字符串转换为 UTF-16 切片
func StringToUTF16(s string) []uint16 {
    return utf16.Encode([]rune(s))
}

// UTF16ToString 将 UTF-16 切片转换为 Go 字符串
func UTF16ToString(s []uint16) string {
    return string(utf16.Decode(s))
}

func main() {
    original := "Hello, 世界!😀"
    
    // 转换为 UTF-16
    utf16Str := StringToUTF16(original)
    fmt.Printf("UTF-16: %v\n", utf16Str)
    
    // 转换回字符串
    recovered := UTF16ToString(utf16Str)
    fmt.Printf("Recovered: %s\n", recovered)
    
    // 验证
    fmt.Printf("Match: %v\n", original == recovered)
}

9. 分析文本的 UTF-16 编码

package main

import (
    "fmt"
    "unicode/utf16"
)

func analyzeUTF16(text string) {
    runes := []rune(text)
    var bmpCount, surrogatePairCount int
    
    for _, r := range runes {
        length := utf16.RuneLen(r)
        if length == 1 {
            bmpCount++
        } else if length == 2 {
            surrogatePairCount++
        }
    }
    
    fmt.Printf("Text: %q\n", text)
    fmt.Printf("Total runes: %d\n", len(runes))
    fmt.Printf("BMP characters: %d\n", bmpCount)
    fmt.Printf("Surrogate pairs: %d\n", surrogatePairCount)
    fmt.Printf("UTF-16 length: %d uint16s\n", 
        bmpCount+surrogatePairCount*2)
    fmt.Println()
}

func main() {
    analyzeUTF16("Hello")
    analyzeUTF16("世界")
    analyzeUTF16("😀😃😄")
    analyzeUTF16("Hello 世界 😀")
}

10. 高效的 UTF-16 编码

package main

import (
    "fmt"
    "unicode/utf16"
)

// 预分配缓冲区进行高效编码
func efficientEncode(text string) []uint16 {
    runes := []rune(text)
    
    // 估算 UTF-16 长度(大多数情况是 1:1)
    estimatedLen := len(runes)
    
    // 预分配缓冲区
    buf := make([]uint16, 0, estimatedLen)
    
    for _, r := range runes {
        buf = utf16.AppendRune(buf, r)
    }
    
    return buf
}

func main() {
    text := "Hello, 世界!😀"
    encoded := efficientEncode(text)
    
    fmt.Printf("Original: %s\n", text)
    fmt.Printf("UTF-16: %v\n", encoded)
    fmt.Printf("Length: %d uint16s\n", len(encoded))
    
    // 解码验证
    decoded := utf16.Decode(encoded)
    fmt.Printf("Decoded: %s\n", string(decoded))
}

最佳实践

1. 使用 Encode/Decode 进行批量转换

// 推荐:批量转换
runes := []rune(text)
utf16Str := utf16.Encode(runes)

// 解码
decoded := utf16.Decode(utf16Str)

2. 使用 AppendRune 增量构建

// 推荐:增量构建
var buf []uint16
for _, r := range runes {
    buf = utf16.AppendRune(buf, r)
}

3. 预分配缓冲区

// 预估长度并预分配
estimatedLen := len(runes)
buf := make([]uint16, 0, estimatedLen)

4. 检查代理对

// 检查是否需要代理对
if utf16.RuneLen(r) == 2 {
    // 需要代理对
    r1, r2 := utf16.EncodeRune(r)
}

5. 处理 NUL 终止符

// Windows API 需要 NUL 终止
utf16Str = append(utf16Str, 0)

// 移除 NUL 终止符
if len(utf16Str) > 0 && utf16Str[len(utf16Str)-1] == 0 {
    utf16Str = utf16Str[:len(utf16Str)-1]
}

6. 验证代理对

// 验证高代理和低代理
if utf16.IsSurrogate(r1) && utf16.IsSurrogate(r2) {
    decoded := utf16.DecodeRune(r1, r2)
}

与其他包配合

unicode/utf8 包

import (
    "unicode/utf8"
    "unicode/utf16"
)

// UTF-8 和 UTF-16 之间转换
func utf8ToUTF16(utf8Str string) []uint16 {
    return utf16.Encode([]rune(utf8Str))
}

func utf16ToUTF8(utf16Str []uint16) string {
    return string(utf16.Decode(utf16Str))
}

syscall 包(Windows)

import (
    "syscall"
    "unicode/utf16"
)

// Windows API 调用
func windowsExample() {
    str := "Hello"
    utf16Str := utf16.Encode([]rune(str))
    
    // 传递给 Windows API
    syscall.SomeWindowsAPI(&utf16Str[0])
}

strings 包

import (
    "strings"
    "unicode/utf16"
)

// 使用 strings.Builder
func buildUTF16(text string) []uint16 {
    var builder strings.Builder
    builder.Grow(len(text))
    builder.WriteString(text)
    
    return utf16.Encode([]rune(builder.String()))
}

注意事项

1. UTF-16 长度不总是等于 rune 数量

text := "😀"  // 1 个 rune
runes := []rune(text)
utf16Str := utf16.Encode(runes)

fmt.Println(len(runes))      // 1
fmt.Println(len(utf16Str))   // 2 (代理对)

2. 代理对本身是无效的

// 代理对不能单独出现
fmt.Println(utf16.IsSurrogate(0xD800))  // true
fmt.Println(utf16.RuneLen(0xD800))      // -1 (无效)

3. BMP 内的字符不需要代理对

// BMP 字符(U+0000 到 U+FFFF)
fmt.Println(utf16.RuneLen('A'))    // 1
fmt.Println(utf16.RuneLen('中'))    // 1

// 辅助平面字符(U+10000 到 U+10FFFF)
fmt.Println(utf16.RuneLen('😀'))   // 2

4. EncodeRune 对 BMP 字符返回特殊值

// BMP 字符不需要代理对
r1, r2 := utf16.EncodeRune('A')
fmt.Printf("r1=U+%04X, r2=U+%04X\n", r1, r2)
// 输出:r1=U+FFFD, r2=U+FFFD (表示不需要代理对)

5. 无效的代理对会被替换

// 不完整的代理对
invalid := []uint16{0xD800}  // 只有高代理
decoded := utf16.Decode(invalid)
fmt.Printf("%c (U+%04X)\n", decoded[0], decoded[0])
// 输出: (U+FFFD)

6. 字节序问题

// UTF-16 有字节序问题(大端/小端)
// Go 的 utf16 包使用本机字节序
// 在网络传输或文件存储时可能需要添加 BOM

7. NUL 字符处理

// UTF-16 中 NUL 是 0x0000
// 与 C 字符串交互时需要注意 NUL 终止符
utf16Str := append(utf16.Encode(runes), 0)  // 添加 NUL 终止

快速参考

函数速查表

函数说明
AppendRune追加 UTF-16 编码到切片
Decode解码 UTF-16 为 rune 序列
DecodeRune解码代理对
Encode编码 rune 序列为 UTF-16
EncodeRune编码单个 rune 为代理对
IsSurrogate检查是否是代理
RuneLen获取 UTF-16 编码长度

Unicode 范围速查表

范围UTF-16 码元数说明
U+0000 - U+D7FF1基本多文种平面(BMP)
U+D800 - U+DBFF-高代理区(无效)
U+DC00 - U+DFFF-低代理区(无效)
U+E000 - U+FFFF1BMP(包括私有区)
U+10000 - U+10FFFF2辅助平面(需要代理对)

代理对范围

类型范围说明
高代理U+D800 - U+DBFF代理对的高位
低代理U+DC00 - U+DFFF代理对的低位

常见模式

// 编码
utf16Str := utf16.Encode([]rune(text))

// 解码
text := string(utf16.Decode(utf16Str))

// 增量构建
var buf []uint16
for _, r := range runes {
    buf = utf16.AppendRune(buf, r)
}

// 检查是否需要代理对
if utf16.RuneLen(r) == 2 {
    // 需要代理对
}

// 编码代理对
r1, r2 := utf16.EncodeRune(r)

// 解码代理对
decoded := utf16.DecodeRune(r1, r2)

总结

unicode/utf16 包提供了完整的 UTF-16 编码支持功能:

核心功能

  • rune 与 UTF-16 码元序列的相互转换
  • 代理对编码和解码
  • UTF-16 长度计算
  • 代理检查

主要函数

  • 编码:EncodeEncodeRuneAppendRune
  • 解码:DecodeDecodeRune
  • 检查:IsSurrogateRuneLen

使用场景

  • Windows API 交互(Windows 使用 UTF-16)
  • Java/.NET 字符串处理
  • 某些文件格式(如 Windows 注册表)
  • 网络协议(如某些版本的 HTTP)

使用建议

  1. 使用 Encode/Decode 进行批量转换
  2. 使用 AppendRune 增量构建
  3. 预分配缓冲区提高效率
  4. 注意代理对的处理
  5. 与 Windows API 交互时添加 NUL 终止符
  6. 理解 BMP 和辅助平面的区别

典型用法

// 编码
utf16Str := utf16.Encode([]rune(text))

// 解码
text := string(utf16.Decode(utf16Str))

// 处理代理对
if utf16.RuneLen(r) == 2 {
    r1, r2 := utf16.EncodeRune(r)
    // 使用 r1, r2
}

通过 unicode/utf16 包,可以方便地处理 UTF-16 编码的文本,特别是与 Windows 系统和其他使用 UTF-16 的平台进行交互。