71

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

1
  • 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. Commented Sep 27, 2014 at 18:54

8 Answers 8

95

You can refer to it as a slice:

pass = string(b[:])
Sign up to request clarification or add additional context in comments.

1 Comment

this does an allocation as it copies b's data into the new string
57

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

5 Comments

Depends on how you print it.
@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
@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.
Why does this fmt.Println(string(b[:])) prints "mostly invalid data" ?
This is the correct answer to receive a md5 hash string. Everything else is not helpful.. requires: import "encoding/hex"
16

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

3 Comments

This is the correct answer in many cases, not the accepted answer
Thank you for reminding me that [n]byte means array and []byte means slice!
Could you please explain why you use base64 here? The question does not mention base64.
9

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
}

5 Comments

Care to explain what is happening there and why is it so much faster?
This code violates recommendations at 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."
go vet also complains about thi in current version, e.g. try in the playground: play.golang.org/p/G6rRGp8jwtW
@RedowanDelowar, the answer was updated. Hope I make myself clearly
4

Make a slice of it:

pass = string(b[:])

Comments

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
}

Comments

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)

Comments

-3

you can try

b.decode("utf-8")

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

1 Comment

No because it’s not Go.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.