【问题标题】:How do I convert [Size]byte to string in Go?如何在 Go 中将 [Size]byte 转换为字符串?
【发布时间】:2014-11-22 06:05:05
【问题描述】:

我在执行md5.Sum() 之后得到了一个大小合适的字节数组。

data := []byte("testing")
var pass string 
var b [16]byte
b = md5.Sum(data)
pass = string(b)

我得到错误:

无法将 b(类型 [16]byte)转换为类型字符串

【问题讨论】:

  • 我想指出,在没有任何盐的情况下创建这样的密码是非常不安全的,也是个坏主意。

标签: go type-conversion


【解决方案1】:

不是为了打印十六进制编码的字符串,而是在一般的情况下[size]byte数组可能包含无效的UTF-8序列,那么根据this answer他们可以被转换使用

转换成有效的UTF-8
s := string([]rune(string(b[:])))

Example:

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {
    b := [1]byte{0xff}
    s := string(b[:])
    fmt.Println(s, []byte(s), utf8.Valid([]byte(s)))
    // Output: � [255] false

    s = string([]rune(string(b[:])))
    fmt.Println(s, []byte(s), utf8.Valid([]byte(s)))
    // Output: � [239 191 189] true
}

【讨论】:

    【解决方案2】:

    你可以试试

    b.decode("utf-8")

    请告诉我,这对你有帮助吗? 强文本

    【讨论】:

      【解决方案3】:

      虽然这里有一些简单的答案,但我想给出一个更有效的解决方案

      ```去 func Bytes2StrImp(b []byte) 字符串{ sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b)) sh := reflect.StringHeader{ 数据:sliceHeader.Data, Len: sliceHeader.Len, } return *(*string)(unsafe.Pointer(&sh)) // 审查错误可能误用 reflect.StringHeader } ```

      更新

      func Bytes2StrImp(b []byte) string {
          sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
          var s string
          sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
          sh.Data = sliceHeader.Data
          sh.Len = sliceHeader.Len
          return s
      }
      

      上述方案只是通过Pointer操作将字节数组转换为字符串。而string(b[:]) 将创建一个新的字符串对象并将数据从字节数组复制到字符串。

      string(b[:]) 的基准测试结果

      func Bytes2StrRaw(b []byte) string {
          return string(b[:])
      }
      
      BenchmarkBytes2StrRaw-12              275305142                4.40 ns/op
      BenchmarkBytes2StrImp-12              1000000000               0.315 ns/op
      

      【讨论】:

      • 想解释一下那里发生了什么,为什么速度这么快?
      • 此代码违反了golang.org/pkg/unsafe/#Pointer 的建议:“一般来说,reflect.SliceHeader 和 reflect.StringHeader 只能用作指向实际切片或字符串的 *reflect.SliceHeader 和 *reflect.StringHeader,从不作为普通结构。程序不应声明或分配这些结构类型的变量。"
      • go vet 在当前版本中也抱怨 thi,例如在操场上尝试:play.golang.org/p/G6rRGp8jwtW
      • @RedowanDelowar,答案已更新。希望我清楚自己
      【解决方案4】:

      可以这样解决

      pass = fmt.Sprintf("%x", b)
      

      import "encoding/base64"
      pass = base64.StdEncoding.EncodeToString(b[:])
      

      这会将其编码为 base64 字符串

      【讨论】:

      • 这是很多情况下的正确答案,不是公认的答案
      • 感谢您提醒我[n]byte 表示数组,[]byte 表示切片!
      【解决方案5】:

      有点晚,但请记住,使用 string(b[:]) 将打印大部分无效字符。

      如果你想像 php 一样获得它的十六进制表示,你可以使用类似的东西:

      data := []byte("testing")
      b := md5.Sum(data)
      
      //this is mostly invalid characters
      fmt.Println(string(b[:]))
      
      pass := hex.EncodeToString(b[:])
      fmt.Println(pass)
      // or
      pass = fmt.Sprintf("%x", b)
      fmt.Println(pass)
      

      playground

      【讨论】:

      • 取决于您的打印方式。
      • @OneOfOne 你确定这是正确的方法。当我运行您提供的游乐场脚本时,我在输出中得到了这个。 �+�QYI��O�+��Uu ae2b1fca515949e5d54fb22b8ed95575 ae2b1fca515949e5d54fb22b8ed95575
      • @NikhilWagh 是正确的,第一个打印将是原始校验和,不适合打印,另外两个将是转换为十六进制的校验和。
      • 为什么fmt.Println(string(b[:])) 会打印“大部分无效数据”?
      • 这是接收 md5 哈希字符串的正确答案。其他一切都没有帮助..要求:import "encoding/hex"
      【解决方案6】:

      您可以将其称为切片:

      pass = string(b[:])
      

      【讨论】:

        【解决方案7】:

        切一块:

        pass = string(b[:])
        

        【讨论】:

          猜你喜欢
          • 2015-03-18
          • 2021-07-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-14
          • 1970-01-01
          • 2020-01-21
          • 1970-01-01
          相关资源
          最近更新 更多