60

I have a sized byte array that I got after doing md5.Sum().

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

I get the error:

cannot convert b (type [16]byte) to type string

JasonMArcher
  • 14,195
  • 22
  • 56
  • 52
Thejus Krishna
  • 1,755
  • 1
  • 19
  • 28
  • 6
    I'd like to point out that creating a password like that without any kind of salt is extremely insecure and a bad idea. – OneOfOne Sep 27 '14 at 18:54

8 Answers8

85

You can refer to it as a slice:

pass = string(b[:])
Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138
52

A little late but keep in mind that using string(b[:]) will print mostly invalid characters.

If you're trying to get a hex representation of it like php you can use something like:

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
  • 95,033
  • 20
  • 184
  • 185
  • Depends on how you print it. –  Sep 29 '14 at 13:45
  • @OneOfOne are you sure this is the correct way to it. I got this at the output when I run the playground script you provided. `�+�QYI��O�+��Uu ae2b1fca515949e5d54fb22b8ed95575 ae2b1fca515949e5d54fb22b8ed95575` – Nikhil Wagh Dec 30 '17 at 18:13
  • @NikhilWagh that is correct, the first print is gonna be the raw checksum, not print-friendly, the other 2 will be the checksum converted to hex. – OneOfOne Jan 10 '18 at 19:05
  • Why does this `fmt.Println(string(b[:]))` prints "mostly invalid data" ? – pkaramol Jan 01 '20 at 15:52
  • 2
    This is the correct answer to receive a md5 hash string. Everything else is not helpful.. requires: `import "encoding/hex"` – ChrisG Jun 06 '20 at 15:30
14

it can be solved by this

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

or

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

this will encoding it to base64 string

chuixue
  • 187
  • 1
  • 4
5

Update 02/01/2023

Per this, unsafe: add StringData, String, SliceData, the reflect.StringHeader and reflect.SliceHeader may be deprecated in Go 1.20. And the unsafe.StringData, unsafe.String, and unsafe.SliceData will replace them, refer to 1.20 release note

The unsafe package defines three new functions SliceData, String, and StringData. Along with Go 1.17's Slice, these functions now provide the complete ability to construct and deconstruct slice and string values, without depending on their exact representation.

func String2Bytes(s string) []byte {
    if s == "" {
        return nil
    }
    return unsafe.Slice(unsafe.StringData(s), len(s))
}

func Bytes2String(b []byte) string {
    if len(b) == 0 {
        return ""
    }
    return unsafe.String(unsafe.SliceData(b), len(b))
}

Before Go 1.20

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
}

The above solution converts the byte array to string through Pointer operation. The string(b[:]) will do a new string object and copy data from the byte array to the string.

Benchmark result with string(b[:])

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

Although there are some simple answers here, I want to give one more efficient solution

func Bytes2StrImp(b []byte) string{
    sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))
    sh := reflect.StringHeader{
        Data: sliceHeader.Data,
        Len:  sliceHeader.Len,
    }
    return *(*string)(unsafe.Pointer(&sh)) // go vet error possible misuse reflect.StringHeader
}

zangw
  • 43,869
  • 19
  • 177
  • 214
  • Care to explain what is happening there and why is it so much faster? – Redowan Delowar Jul 01 '21 at 21:16
  • This code violates recommendations at https://golang.org/pkg/unsafe/#Pointer: "In general, reflect.SliceHeader and reflect.StringHeader should be used only as *reflect.SliceHeader and *reflect.StringHeader pointing at actual slices or strings, never as plain structs. A program should not declare or allocate variables of these struct types." – Duncan Harris Jul 05 '21 at 22:44
  • `go vet` also complains about thi in current version, e.g. try in the playground: https://play.golang.org/p/G6rRGp8jwtW – Duncan Harris Jul 05 '21 at 22:49
  • 1
    Correct code: https://play.golang.org/p/Lh28f4HF_W9 – Duncan Harris Jul 05 '21 at 22:51
  • 1
    @RedowanDelowar, the answer was updated. Hope I make myself clearly – zangw Jul 06 '21 at 05:33
4

Make a slice of it:

pass = string(b[:])
0

Not for printing hex-encoded strings, but in the general case when the [size]byte array may contain invalid UTF-8 sequence(s), then according to this answer they can be converted into valid UTF-8 using

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
}
dan
  • 1,144
  • 12
  • 17
0

I found these comments really unhelpful because they assume OP just wants a literal string of the []byte.... but if you were like me and need utf8 decoded bytes as a string you can use this:

import  "unicode/utf8"
func bytesToUtf8(b []byte) string {
    var myString = "";
    for i := 1; i <= len(b); i++ {
        r, _ := utf8.DecodeRune(b[i-1:i])
        myString += string(r)
    }
    return myString
}
var uselessBytes := []byte{123,34,...}
helpfulUtf8String := bytesToUtf8(uselessBytes)
Pandem1c
  • 778
  • 1
  • 5
  • 12
-3

you can try

b.decode("utf-8")

please let me know, is that help you or not? strong text

Nkgupta
  • 144
  • 1
  • 6