在 go 中,`unsigned char` 对应 `byte`(即 `uint8`),`unsigned char*` 不应直接用指针模拟,而应使用 `[]byte` 切片配合整数索引——go 不支持指针算术,切片已内置安全高效的底层操作。

| C/C++ 类型 | Go 等价类型 | 说明 |
|---|---|---|
| unsigned char | byte(= uint8) | 表示单个 0–255 的无符号字节,不是字符串或 rune |
| unsigned char[N] | [N]byte | 固定长度数组,如状态表 m_aucState0 [256]byte |
| unsigned char* | 不直接对应指针,而用 []byte + int 索引 | Go 禁止 ptr + i 这类指针算术;改用 slice[i] 或 slice[i:j] |
// ❌ 错误:不能声明 *m_pucState1 []byte(语法非法),也不应为单字节字段用 []byte
m_ucI, m_ucJ []byte // × 错误:它们是单字节索引,不是字节序列
*m_pucState1 []byte // × 语法错误,且语义错误
m_ucTemp []byte // × 应为 byte
// ✅ 正确重写结构体:
type ArcfourPRNG struct {
m_bInit bool
m_aucState0 [256]byte // 固定大小状态数组
m_aucState [256]byte
m_ucI, m_ucJ byte // 单字节索引变量(uint8 范围足够)
m_ucTemp byte
// 指针字段完全移除:用整数索引 + 切片访问替代
}C++ 原逻辑(含指针算术):
for(i = 0; i < 256; i++) {
m_pucState1 = m_aucState0 + i; // ptr to element i
m_ucJ += *m_pucState1 + *(pucKeyData + m_ucI);
m_pucState2 = m_aucState0 + m_ucJ; // ptr to element m_ucJ
// swap *m_pucState1 ↔ *m_pucState2
m_ucTemp = *m_pucState1;
*m_pucState1 = *m_pucState2;
*m_pucState2 = m_ucTemp;
m_ucI = (m_ucI + 1) % iKeyLen;
}
memcpy(m_aucState, m_aucState0, 256); // copy entire array✅ Go 等价实现(清晰、安全、无指针):
func (arc4 *ArcfourPRNG) SetKey(key []byte, keyLen int) {
// 初始化 m_aucState0: 0,1,2,...,255
for i := 0; i < 256; i++ {
arc4.m_aucState0[i] = byte(i)
}
var j byte = 0
for i := 0; i < 256; i++ {
// 直接索引:arc4.m_aucState0[i] 替代 *(m_aucState0 + i)
j += arc4.m_aucState0[i] + key[i%keyLen] // key[i%keyLen] 替代 *(pucKeyData + m_ucI)
// 交换 arc4.m_aucState0[i] ↔ arc4.m_aucState0[j]
arc4.m_aucState0[i], arc4.m_aucState0[j] = arc4.m_aucState0[j], arc4.m_aucState0[i]
}
// 复制到工作状态数组(Go 中用 copy() 安全高效)
copy(arc4.m_aucState[:], arc4.m_aucState0[:])
}将 C/C++ 的 unsigned char* 机械翻译为 Go 指针是反模式。Go 的设计哲学是用更高级的抽象(切片 + 索引)取代底层指针算术,既提升安全性,又不牺牲性能。重写 ARC4 时,专注算法逻辑本身——用 byte 表示状态变量,用 [256]byte 表示固定表,用 []byte 和整数索引处理动态数据流。你很快会发现,Go 版本比 C++ 更简洁、更易验证正确性。