Foreword: The first section answers the original question (encode array to Base64). If you just want individual string fields to appear as Base64 strings in the output, see the 2nd section.
Encoding a []string into Base64 format
Base64 is an encoding, a function used to convert an arbitrary sequence of bytes to a text using a small, well defined set of characters.
So you have to decide / come up with a way to convert your []string array or slice to a sequence of bytes.
An easy and convenient way is to convert your []string to JSON text which will also take care of escaping strings having a quotation mark " for example. The result string can be easily encoded using the method you described:
genre := []string{"Pop", "Rock", "Dance", "Opera", "Techno", "Hiphop", "Jazz", "Reggae"}
data, _ := json.Marshal(&genre)
fmt.Println(string(data))
sEnc := base64.StdEncoding.EncodeToString(data)
fmt.Println(sEnc)
Output (try it on the Go Playground):
["Pop","Rock","Dance","Opera","Techno","Hiphop","Jazz","Reggae"]
WyJQb3AiLCJSb2NrIiwiRGFuY2UiLCJPcGVyYSIsIlRlY2hubyIsIkhpcGhvcCIsIkphenoiLCJSZWdnYWUiXQ==
Decoding
Having such Base64 result, you can decode it like this:
data2, err := base64.StdEncoding.DecodeString(sEnc)
if err != nil {
panic(err)
}
var genre2 []string
if err = json.Unmarshal(data2, &genre2); err != nil {
panic(err)
}
fmt.Println(genre2)
Output:
[Pop Rock Dance Opera Techno Hiphop Jazz Reggae]
Notes:
Of course you may choose any other transformations to convert []string to a byte sequence. You could convert it to XML, or using the encoding/binary or anything else. I chose JSON because it is a one-liner, compact, fast, and is supported in almost every programming language, so it won't be a problem if another program has to decode it.
Making individual string fields to appear as Base64
You can do this by implementing the Marshaler interface on the type (or enclosing struct) like this:
func (g *Genre) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
g2 := *g
g2.Title = base64.StdEncoding.EncodeToString([]byte(g.Title))
return e.EncodeElement(g2, start)
}
Basically what this does is creates a copy of Genre, changes the value of the Title field (of the copy) to the Base64 representation of its original value and encodes this copy.
Output (partial), try it on the Go Playground:
<GenreArray>
<item>
<genre>UG9w</genre>
</item>
<item>
<genre>Um9jaw==</genre>
</item>
</GenreArray>
Answer from icza on Stack OverflowEncode []byte as base64 string (to be consistent with stdlib JSON)
Convert data to base64 encode in go - Stack Overflow
Explain why []byte is base64 encoded when marshalled to json?
Base64 is the most widely used text representation of binary data.
More on reddit.comIs it a good idea to convert images into base64 string and save them in database?
The len prefix is superficial and causes the invalid utf-8 error:
package main
import (
"encoding/base64"
"fmt"
"log"
)
func main() {
str := base64.StdEncoding.EncodeToString([]byte("Hello, playground"))
fmt.Println(str)
data, err := base64.StdEncoding.DecodeString(str)
if err != nil {
log.Fatal("error:", err)
}
fmt.Printf("%q\n", data)
}
(Also here)
Output
SGVsbG8sIHBsYXlncm91bmQ=
"Hello, playground"
EDIT: I read too fast, the len was not used as a prefix. dystroy got it right.
DecodedLen returns the maximal length.
This length is useful for sizing your buffer but part of the buffer won't be written and thus won't be valid UTF-8.
You have to use only the real written length returned by the Decode function.
l, _ := base64.StdEncoding.Decode(base64Text, []byte(message))
log.Printf("base64: %s\n", base64Text[:l])
I am not sure what exactly is not clear from the documentation. Not only it has a clear name which explains states what the method is doing, it also has an example.
package main
import (
"encoding/base64"
"fmt"
)
func main() {
data := []byte("Pop")
str := base64.StdEncoding.EncodeToString(data)
fmt.Println(str) // UG9w
}
Go Playground
You can customise the output of print functions by providing a String() method for your type. Either for the whole Genre or just for the name variable.
Example:
package main
import (
"encoding/base64"
"fmt"
)
type Base64String string
func (b Base64String) String() string {
return base64.StdEncoding.EncodeToString([]byte(b))
}
type Genre struct {
Name Base64String
}
func main() {
a := []Genre{Genre{"Pop"}, Genre{"Rock"}}
fmt.Println(a) // prints [{UG9w} {Um9jaw==}]
fmt.Println(string(a[0].Name)) // prints Pop
}
This is documented in the json package:
โ... []byte encodes as a base64-encoded string ...โ
Iโm curious about the motivation behind this design? Do other languages do this?
I understand that base64 encoding is done to transport binary data through transport mechanisms that are better at handling text. I guess you wouldnโt want a json array because it would be less efficient to marshal/unmarshal vs a string.
Base64 is the most widely used text representation of binary data.
It's because []byte != string if you've come from C or similar and have been using byte as a char replacement. You need some way to safely transport bytes since JSON values can only be string (UTF-8), number, object, array, bool & null.
I don't know about other languages but if you use Array#pack in Ruby to build a 'binary string' then JSON#generate will raise an Encoding::UndefinedConversionError exception if your 'binary string' can't be converted to UTF-8. So in Ruby you need to encode binary data (with base64, an array of integers to use with unpack or whatever) yourself to safely use it in JSON.