英文:
Encode array to base64 in go
问题
这是我开发的一个函数的完整代码:
package main
import (
"database/sql"
"log"
"encoding/xml"
"github.com/gin-gonic/gin" //golang frameworks
_ "github.com/go-sql-driver/mysql"
"gopkg.in/gorp.v1" //work with database(mysql, etc.)
)
type Genre struct {
Title string `xml:"genre"`
}
type GenreArray struct {
Auth_state int `xml:"auth_state"`
Count int64 `xml:"count"`
Item genreAPI `xml:"item"`
}
type UserPass struct {
Username string `xml:"username"`
Password string `xml:"password"`
}
type ErrorMessage struct {
XMLName xml.Name `xml:"error"`
Error string `xml:"error_code"`
Message string `xml:"message"`
}
type Auth struct {
XMLName xml.Name `xml:"config"`
Nas_SharingEmpty int `xml:"nas_sharing>auth_state"`
}
type ConfigGenre struct {
XMLName xml.Name `xml:"config"`
Nas_Sharing GenreArray `xml:"nas_sharing"`
}
type genreAPI []Genre
var dbmap = initDb()
func initDb() *gorp.DbMap {
db, err := sql.Open("mysql", "root@tcp(localhost:3306)/mymusic")
checkErr(err, "sql.Open failed")
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}}
return dbmap
}
func checkErr(err error, msg string) {
if err != nil {
log.Fatalln(msg, err)
}
}
func main() {
r := gin.Default()
r.POST("/nas_sharing", myMusicXML)
r.Run(":9999")
}
func myMusicXML(c *gin.Context) {
c.Request.ParseForm()
cmd := c.Request.Form.Get("cmd")
usernamepost := c.Request.Form.Get("user")
passwordpost := c.Request.Form.Get("passwd")
if cmd == "36" {
//Music Genre List API
var genre []Genre
var userpass []UserPass
var count int64
var countAuth int64
//Query the post username and password
_, errAuth := dbmap.Select(&userpass, "SELECT username, password FROM user WHERE username=? and password=?", usernamepost, passwordpost)
//Check if post username and password exist
countAuth, errAuth = dbmap.SelectInt("select count(*) FROM user WHERE username=? and password=?", usernamepost, passwordpost)
if countAuth == 0 {
//If no rows detected, output a message
c.XML(404, Auth{Nas_SharingEmpty: 0})
}else{
//Check if query is valid
if errAuth == nil {
log.Println("auth_state :", countAuth)
}else{
c.XML(404, gin.H{"error": "sql query error found"})
}
//Query genre list
_, err := dbmap.Select(&genre, "SELECT Title FROM genre_cntr_tbl")
//Count genres
count, err = dbmap.SelectInt("select count(*) FROM genre_cntr_tbl")
if count == 0 {
//If no rows detected, output a message
c.XML(404, ErrorMessage{Error:"404", Message: "no genre found"})
}else{
//Check if query is valid
if err == nil {
log.Println("Genres :", genre)
c.XML(200, ConfigGenre{Nas_Sharing: GenreArray{Auth_state: 1, Count: count, Item: genre,}})
}else{
c.XML(404, gin.H{"error": "sql query error found"})
}
}
}
}else{
c.XML(404, ErrorMessage{Error:"404", Message: "command not found"})
}
}
这是我的输出结果:
<config>
<nas_sharing>
<auth_state>1</auth_state>
<count>8</count>
<item>
<genre>Pop</genre>
</item>
<item>
<genre>Rock</genre>
</item>
<item>
<genre>Dance</genre>
</item>
<item>
<genre>Opera</genre>
</item>
<item>
<genre>Techno</genre>
</item>
<item>
<genre>Hip Hop</genre>
</item>
<item>
<genre>Jazz</genre>
</item>
<item>
<genre>Reggae</genre>
</item>
</nas_sharing>
</config>
这是我输出到日志中的 genre 值(注意:它来自数据库):
Genres : [{Pop} {Rock} {Dance} {Opera} {Techno} {Hiphop} {Jazz} {Reggae}]
然而,我想将输出转换为 base64 格式。这是一个将数据编码为 base64 的示例代码,但是给定的数据是 string
,不像我开发的那个来自数组。我该如何实现这个输出?
data := "/MyMusic/images/_albums/albums_nophoto.png"
sEnc := b64.StdEncoding.EncodeToString([]byte(data))
fmt.Println(sEnc)
这是我期望的输出:
<config>
<nas_sharing>
<auth_state>1</auth_state>
<count>8</count>
<item>
<genre>UG9w</genre>
</item>
<item>
<genre>Um9jaw==</genre>
</item>
<item>
<genre>RGFuY2U=</genre>
</item>
<item>
<genre>T3BlcmE=</genre>
</item>
<item>
<genre>VGVjaG5v</genre>
</item>
etc...
英文:
Here is my complete code for a function I develop:
package main
import (
"database/sql"
"log"
"encoding/xml"
"github.com/gin-gonic/gin" //golang frameworks
_ "github.com/go-sql-driver/mysql"
"gopkg.in/gorp.v1" //work with database(mysql, etc.)
)
type Genre struct {
Title string `xml:"genre"`
}
type GenreArray struct {
Auth_state int `xml:"auth_state"`
Count int64 `xml:"count"`
Item genreAPI `xml:"item"`
}
type UserPass struct {
Username string `xml:"username"`
Password string `xml:"password"`
}
type ErrorMessage struct {
XMLName xml.Name `xml:"error"`
Error string `xml:"error_code"`
Message string `xml:"message"`
}
type Auth struct {
XMLName xml.Name `xml:"config"`
Nas_SharingEmpty int `xml:"nas_sharing>auth_state"`
}
type ConfigGenre struct {
XMLName xml.Name `xml:"config"`
Nas_Sharing GenreArray `xml:"nas_sharing"`
}
type genreAPI []Genre
var dbmap = initDb()
func initDb() *gorp.DbMap {
db, err := sql.Open("mysql", "root@tcp(localhost:3306)/mymusic")
checkErr(err, "sql.Open failed")
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}}
return dbmap
}
func checkErr(err error, msg string) {
if err != nil {
log.Fatalln(msg, err)
}
}
func main() {
r := gin.Default()
r.POST("/nas_sharing", myMusicXML)
r.Run(":9999")
}
func myMusicXML(c *gin.Context) {
c.Request.ParseForm()
cmd := c.Request.Form.Get("cmd")
usernamepost := c.Request.Form.Get("user")
passwordpost := c.Request.Form.Get("passwd")
if cmd == "36" {
//Music Genre List API
var genre []Genre
var userpass []UserPass
var count int64
var countAuth int64
//Query the post username and password
_, errAuth := dbmap.Select(&userpass, "SELECT username, password FROM user WHERE username=? and password=?", usernamepost, passwordpost)
//Check if post username and password exist
countAuth, errAuth = dbmap.SelectInt("select count(*) FROM user WHERE username=? and password=?", usernamepost, passwordpost)
if countAuth == 0 {
//If no rows detected, output a message
c.XML(404, Auth{Nas_SharingEmpty: 0})
}else{
//Check if query is valid
if errAuth == nil {
log.Println("auth_state :", countAuth)
}else{
c.XML(404, gin.H{"error": "sql query error found"})
}
//Query genre list
_, err := dbmap.Select(&genre, "SELECT Title FROM genre_cntr_tbl")
//Count genres
count, err = dbmap.SelectInt("select count(*) FROM genre_cntr_tbl")
if count == 0 {
//If no rows detected, output a message
c.XML(404, ErrorMessage{Error:"404", Message: "no genre found"})
}else{
//Check if query is valid
if err == nil {
log.Println("Genres :", genre)
c.XML(200, ConfigGenre{Nas_Sharing: GenreArray{Auth_state: 1, Count: count, Item: genre,}})
}else{
c.XML(404, gin.H{"error": "sql query error found"})
}
}
}
}else{
c.XML(404, ErrorMessage{Error:"404", Message: "command not found"})
}
}
And here is the output:
<config>
<nas_sharing>
<auth_state>1</auth_state>
<count>8</count>
<item>
<genre>Pop</genre>
</item>
<item>
<genre>Rock</genre>
</item>
<item>
<genre>Dance</genre>
</item>
<item>
<genre>Opera</genre>
</item>
<item>
<genre>Techno</genre>
</item>
<item>
<genre>Hip Hop</genre>
</item>
<item>
<genre>Jazz</genre>
</item>
<item>
<genre>Reggae</genre>
</item>
</nas_sharing>
</config>
Here is the value of genre of my output to log(note: It came from a database):
Genres : [{Pop} {Rock} {Dance} {Opera} {Techno} {Hiphop} {Jazz} {Reggae}]
However, I would like to convert the output to base64 format. Here's a sample code for encoding to base64 but the data given to this is string
unlike the one I develop that comes from an array. How could I achieve that output?
data := "/MyMusic/images/_albums/albums_nophoto.png"
sEnc := b64.StdEncoding.EncodeToString([]byte(data))
fmt.Println(sEnc)
Here is what output I expected
<config>
<nas_sharing>
<auth_state>1</auth_state>
<count>8</count>
<item>
<genre>UG9w</genre>
</item>
<item>
<genre>Um9jaw==</genre>
</item>
<item>
<genre>RGFuY2U=</genre>
</item>
<item>
<genre>T3BlcmE=</genre>
</item>
<item>
<genre>VGVjaG5v</genre>
</item>
etc...
答案1
得分: 3
将[]string
编码为Base64格式
Base64是一种编码方式,用于将任意字节序列转换为文本,使用一组小而明确定义的字符。
因此,您需要决定/想出一种将[]string
数组或切片转换为字节序列的方法。
一种简单方便的方法是将[]string
转换为JSON文本,这也会处理转义字符串中的引号"
。可以使用您描述的方法轻松地对结果string
进行编码:
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)
输出(在Go Playground上尝试):
["Pop","Rock","Dance","Opera","Techno","Hiphop","Jazz","Reggae"]
WyJQb3AiLCJSb2NrIiwiRGFuY2UiLCJPcGVyYSIsIlRlY2hubyIsIkhpcGhvcCIsIkphenoiLCJSZWdnYWUiXQ==
解码
有了这样的Base64结果,您可以这样解码:
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)
输出:
[Pop Rock Dance Opera Techno Hiphop Jazz Reggae]
注意:
当然,您可以选择任何其他转换方式将[]string
转换为字节序列。您可以将其转换为XML,或使用encoding/binary
或其他任何方式。我选择JSON是因为它是一行代码,紧凑,快速,并且几乎在每种编程语言中都受支持,因此如果另一个程序需要解码它,这不会成为问题。
使单独的string
字段显示为Base64
您可以通过在类型(或封闭的struct
)上实现Marshaler
接口来实现此目的,示例如下:
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)
}
基本上,这将创建Genre
的副本,将副本的Title
字段值更改为其原始值的Base64表示,并对此副本进行编码。
输出(部分),在Go Playground上尝试:
<GenreArray>
<item>
<genre>UG9w</genre>
</item>
<item>
<genre>Um9jaw==</genre>
</item>
</GenreArray>
英文:
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论