连接[] byte和哈希

I have something like

unixtime := time.Now().Unix()

unixtimeStr := string(unixtime)

soup := make([]byte, len(data) + len(nonce) + len(unixtimeStr) + len(previousHash))

copy(soup[:], data)
copy(soup[len(data):], nonce)
copy(soup[len(data) + len(nonce):], []byte(unixtimeStr))
copy(soup[len(data) + len(nonce) + len(unixtimeStr):], previousHash)

hasher := sha1.New()
hasher.Write(soup)
var hash []byte = hasher.Sum(nil)

data, nonce, previousHash are of type []byte.

I find it so dirty and unreadable!

I'd like a more object oriented coding style like

soup := data.concat(nonce).concat([]byte(unixtimeStr)).concat(previousHash)

or at least something like

soup := concat(data, nonce, ...)

How would you write this snippet?

For example,

var data, nonce, previousHash []byte

unixtime := strconv.FormatInt(time.Now().Unix(), 10)
hasher := sha1.New()
hasher.Write(data)
hasher.Write(nonce)
hasher.Write([]byte(unixtime))
hasher.Write(previousHash)
hash := hasher.Sum(nil)

Or,

var data, nonce, previousHash []byte

unixtime := strconv.FormatInt(time.Now().Unix(), 10)
soup := make([]byte, 0, len(data)+len(nonce)+len(unixtime)+len(previousHash))
soup = append(soup, data...)
soup = append(soup, nonce...)
soup = append(soup, unixtime...)
soup = append(soup, previousHash...)
hasher := sha1.New()
hasher.Write(soup)
hash := hasher.Sum(nil)

Note:

unixtime := time.Now().Unix()
unixtimeStr := string(unixtime)

is nonsensical. It's always the Unicode replacement character. For example,

package main

import (
    "fmt"
    "time"
    "unicode"
)

func main() {
    unixtime := time.Now().Unix()
    unixtimeStr := string(unixtime)
    fmt.Println(unixtimeStr == string(unicode.ReplacementChar))
}

Output:

true

To convert an integer to a string, use the strconv package. For example,

package main

import (
    "fmt"
    "strconv"
    "time"
)

func main() {
    unixtimeStr := strconv.FormatInt(time.Now().Unix(), 10)
    fmt.Println(unixtimeStr)
}

Output:

1257894000

I should point out that hash.Hash is an io.Writer so you can pass it as the first argument to fmt.Fprintf(...) -- and, since fmt does the Right Thing for byte slices with its %s verb, you could make this a lot more readable by:

h := sha1.New()
fmt.Fprintf(h, "%s%s%d%s", data, nonce, time.Now().Unix(), prev)

...and, it takes care of your integer conversion for you too (with the %d)

(Obligatory Go Playground Link)

Note: fmt.Fprintf(...) is not terribly fast; if performance is important you should find another way to do this. Performance and readability are often a delicate balance.