Go CityHash64 Code Example (Online Runner)
Go CityHash64 examples with decimal output and file hashing to match the CityHash tools.
Online calculator: use the site CityHash text tool.
Calculation method
CityHash64 returns a 64-bit integer. The tool displays the unsigned decimal value.
Implementation notes
- Package: no external dependencies; this is a pure Go CityHash64 implementation.
- Implementation: output is formatted as an unsigned base-10 string.
- Notes: CityHash is not cryptographic; use it for hash tables or checksums only.
Text hashing example
go
package main
import (
"encoding/binary"
"fmt"
"math/bits"
"strconv"
)
const (
k0 uint64 = 0xc3a5c85c97cb3127
k1 uint64 = 0xb492b66fbe98f273
k2 uint64 = 0x9ae16a3b2f90404f
k3 uint64 = 0xc949d7c7509e6557
)
type uint128 struct {
first uint64
second uint64
}
func rotate(val uint64, shift uint) uint64 {
if shift == 0 {
return val
}
return bits.RotateLeft64(val, int(shift))
}
func shiftMix(val uint64) uint64 {
return val ^ (val >> 47)
}
func fetch64(data []byte, offset int) uint64 {
return binary.LittleEndian.Uint64(data[offset:])
}
func fetch32(data []byte, offset int) uint64 {
return uint64(binary.LittleEndian.Uint32(data[offset:]))
}
func hash128to64(x uint128) uint64 {
const kMul uint64 = 0x9ddfea08eb382d69
a := (x.first ^ x.second) * kMul
a ^= a >> 47
b := (x.second ^ a) * kMul
b ^= b >> 47
b *= kMul
return b
}
func hashLen16(u, v uint64) uint64 {
return hash128to64(uint128{first: u, second: v})
}
func hashLen0to16(s []byte) uint64 {
length := len(s)
if length > 8 {
a := fetch64(s, 0)
b := fetch64(s, length-8)
return hashLen16(a, rotate(b+uint64(length), uint(length))) ^ b
}
if length >= 4 {
a := fetch32(s, 0)
return hashLen16(uint64(length)+(a<<3), fetch32(s, length-4))
}
if length > 0 {
a := uint64(s[0])
b := uint64(s[length>>1])
c := uint64(s[length-1])
y := a + (b << 8)
z := uint64(length) + (c << 2)
return shiftMix(y*k2^z*k3) * k2
}
return k2
}
func hashLen17to32(s []byte) uint64 {
length := len(s)
a := fetch64(s, 0) * k1
b := fetch64(s, 8)
c := fetch64(s, length-8) * k2
d := fetch64(s, length-16) * k0
return hashLen16(rotate(a-b, 43)+rotate(c, 30)+d, a+rotate(b^k3, 20)-c+uint64(length))
}
func weakHashLen32WithSeeds(w, x, y, z, a, b uint64) uint128 {
a += w
b = rotate(b+a+z, 21)
c := a
a += x
a += y
b += rotate(a, 44)
return uint128{first: a + z, second: b + c}
}
func weakHashLen32WithSeedsFromArray(s []byte, offset int, a, b uint64) uint128 {
return weakHashLen32WithSeeds(
fetch64(s, offset),
fetch64(s, offset+8),
fetch64(s, offset+16),
fetch64(s, offset+24),
a,
b,
)
}
func hashLen33to64(s []byte) uint64 {
length := len(s)
z := fetch64(s, 24)
a := fetch64(s, 0) + (uint64(length)+fetch64(s, length-16))*k0
b := rotate(a+z, 52)
c := rotate(a, 37)
a += fetch64(s, 8)
c += rotate(a, 7)
a += fetch64(s, 16)
vf := a + z
vs := b + rotate(a, 31) + c
a = fetch64(s, 16) + fetch64(s, length-32)
z2 := fetch64(s, length-8)
b = rotate(a+z2, 52)
c = rotate(a, 37)
a += fetch64(s, length-24)
c += rotate(a, 7)
a += fetch64(s, length-16)
wf := a + z2
ws := b + rotate(a, 31) + c
r := shiftMix((vf+ws)*k2 + (wf+vs)*k0)
return shiftMix(r*k0+vs) * k2
}
func cityHash64(data []byte) uint64 {
length := len(data)
if length <= 32 {
if length <= 16 {
return hashLen0to16(data)
}
return hashLen17to32(data)
}
if length <= 64 {
return hashLen33to64(data)
}
x := fetch64(data, 0)
y := fetch64(data, length-16) ^ k1
z := fetch64(data, length-56) ^ k0
v := weakHashLen32WithSeedsFromArray(data, length-64, uint64(length), y)
w := weakHashLen32WithSeedsFromArray(data, length-32, uint64(length)*k1, k0)
z += shiftMix(v.second) * k1
x = rotate(z+x, 39) * k1
y = rotate(y, 33) * k1
currentLen := (length - 1) &^ 63
offset := 0
for currentLen > 0 {
x = rotate(x+y+v.first+fetch64(data, offset+16), 37) * k1
y = rotate(y+v.second+fetch64(data, offset+48), 42) * k1
x ^= w.second
y ^= v.first
z = rotate(z^w.first, 33)
v = weakHashLen32WithSeedsFromArray(data, offset, v.second*k1, x+w.first)
w = weakHashLen32WithSeedsFromArray(data, offset+32, z+w.second, y)
z, x = x, z
offset += 64
currentLen -= 64
}
return hashLen16(hashLen16(v.first, w.first)+shiftMix(y)*k1+z, hashLen16(v.second, w.second)+x)
}
func cityHash64Text(text string) string {
value := cityHash64([]byte(text))
return strconv.FormatUint(value, 10)
}
func main() {
fmt.Println(cityHash64Text("hello"))
}File hashing example
go
package main
import (
"encoding/binary"
"fmt"
"math/bits"
"os"
"strconv"
)
const (
k0 uint64 = 0xc3a5c85c97cb3127
k1 uint64 = 0xb492b66fbe98f273
k2 uint64 = 0x9ae16a3b2f90404f
k3 uint64 = 0xc949d7c7509e6557
)
type uint128 struct {
first uint64
second uint64
}
func rotate(val uint64, shift uint) uint64 {
if shift == 0 {
return val
}
return bits.RotateLeft64(val, int(shift))
}
func shiftMix(val uint64) uint64 {
return val ^ (val >> 47)
}
func fetch64(data []byte, offset int) uint64 {
return binary.LittleEndian.Uint64(data[offset:])
}
func fetch32(data []byte, offset int) uint64 {
return uint64(binary.LittleEndian.Uint32(data[offset:]))
}
func hash128to64(x uint128) uint64 {
const kMul uint64 = 0x9ddfea08eb382d69
a := (x.first ^ x.second) * kMul
a ^= a >> 47
b := (x.second ^ a) * kMul
b ^= b >> 47
b *= kMul
return b
}
func hashLen16(u, v uint64) uint64 {
return hash128to64(uint128{first: u, second: v})
}
func hashLen0to16(s []byte) uint64 {
length := len(s)
if length > 8 {
a := fetch64(s, 0)
b := fetch64(s, length-8)
return hashLen16(a, rotate(b+uint64(length), uint(length))) ^ b
}
if length >= 4 {
a := fetch32(s, 0)
return hashLen16(uint64(length)+(a<<3), fetch32(s, length-4))
}
if length > 0 {
a := uint64(s[0])
b := uint64(s[length>>1])
c := uint64(s[length-1])
y := a + (b << 8)
z := uint64(length) + (c << 2)
return shiftMix(y*k2^z*k3) * k2
}
return k2
}
func hashLen17to32(s []byte) uint64 {
length := len(s)
a := fetch64(s, 0) * k1
b := fetch64(s, 8)
c := fetch64(s, length-8) * k2
d := fetch64(s, length-16) * k0
return hashLen16(rotate(a-b, 43)+rotate(c, 30)+d, a+rotate(b^k3, 20)-c+uint64(length))
}
func weakHashLen32WithSeeds(w, x, y, z, a, b uint64) uint128 {
a += w
b = rotate(b+a+z, 21)
c := a
a += x
a += y
b += rotate(a, 44)
return uint128{first: a + z, second: b + c}
}
func weakHashLen32WithSeedsFromArray(s []byte, offset int, a, b uint64) uint128 {
return weakHashLen32WithSeeds(
fetch64(s, offset),
fetch64(s, offset+8),
fetch64(s, offset+16),
fetch64(s, offset+24),
a,
b,
)
}
func hashLen33to64(s []byte) uint64 {
length := len(s)
z := fetch64(s, 24)
a := fetch64(s, 0) + (uint64(length)+fetch64(s, length-16))*k0
b := rotate(a+z, 52)
c := rotate(a, 37)
a += fetch64(s, 8)
c += rotate(a, 7)
a += fetch64(s, 16)
vf := a + z
vs := b + rotate(a, 31) + c
a = fetch64(s, 16) + fetch64(s, length-32)
z2 := fetch64(s, length-8)
b = rotate(a+z2, 52)
c = rotate(a, 37)
a += fetch64(s, length-24)
c += rotate(a, 7)
a += fetch64(s, length-16)
wf := a + z2
ws := b + rotate(a, 31) + c
r := shiftMix((vf+ws)*k2 + (wf+vs)*k0)
return shiftMix(r*k0+vs) * k2
}
func cityHash64(data []byte) uint64 {
length := len(data)
if length <= 32 {
if length <= 16 {
return hashLen0to16(data)
}
return hashLen17to32(data)
}
if length <= 64 {
return hashLen33to64(data)
}
x := fetch64(data, 0)
y := fetch64(data, length-16) ^ k1
z := fetch64(data, length-56) ^ k0
v := weakHashLen32WithSeedsFromArray(data, length-64, uint64(length), y)
w := weakHashLen32WithSeedsFromArray(data, length-32, uint64(length)*k1, k0)
z += shiftMix(v.second) * k1
x = rotate(z+x, 39) * k1
y = rotate(y, 33) * k1
currentLen := (length - 1) &^ 63
offset := 0
for currentLen > 0 {
x = rotate(x+y+v.first+fetch64(data, offset+16), 37) * k1
y = rotate(y+v.second+fetch64(data, offset+48), 42) * k1
x ^= w.second
y ^= v.first
z = rotate(z^w.first, 33)
v = weakHashLen32WithSeedsFromArray(data, offset, v.second*k1, x+w.first)
w = weakHashLen32WithSeedsFromArray(data, offset+32, z+w.second, y)
z, x = x, z
offset += 64
currentLen -= 64
}
return hashLen16(hashLen16(v.first, w.first)+shiftMix(y)*k1+z, hashLen16(v.second, w.second)+x)
}
func cityHash64File(path string) (string, error) {
data, err := os.ReadFile(path)
if err != nil {
return "", err
}
value := cityHash64(data)
return strconv.FormatUint(value, 10), nil
}
func main() {
file, err := os.CreateTemp("", "cityhash-example-*.bin")
if err != nil {
panic(err)
}
defer os.Remove(file.Name())
file.WriteString("hello")
file.Close()
value, err := cityHash64File(file.Name())
if err != nil {
panic(err)
}
fmt.Println(value)
}Complete script (implementation + tests)
go
package main
import (
"encoding/binary"
"fmt"
"math/bits"
"os"
"strconv"
)
const (
k0 uint64 = 0xc3a5c85c97cb3127
k1 uint64 = 0xb492b66fbe98f273
k2 uint64 = 0x9ae16a3b2f90404f
k3 uint64 = 0xc949d7c7509e6557
)
type uint128 struct {
first uint64
second uint64
}
func rotate(val uint64, shift uint) uint64 {
if shift == 0 {
return val
}
return bits.RotateLeft64(val, int(shift))
}
func shiftMix(val uint64) uint64 {
return val ^ (val >> 47)
}
func fetch64(data []byte, offset int) uint64 {
return binary.LittleEndian.Uint64(data[offset:])
}
func fetch32(data []byte, offset int) uint64 {
return uint64(binary.LittleEndian.Uint32(data[offset:]))
}
func hash128to64(x uint128) uint64 {
const kMul uint64 = 0x9ddfea08eb382d69
a := (x.first ^ x.second) * kMul
a ^= a >> 47
b := (x.second ^ a) * kMul
b ^= b >> 47
b *= kMul
return b
}
func hashLen16(u, v uint64) uint64 {
return hash128to64(uint128{first: u, second: v})
}
func hashLen0to16(s []byte) uint64 {
length := len(s)
if length > 8 {
a := fetch64(s, 0)
b := fetch64(s, length-8)
return hashLen16(a, rotate(b+uint64(length), uint(length))) ^ b
}
if length >= 4 {
a := fetch32(s, 0)
return hashLen16(uint64(length)+(a<<3), fetch32(s, length-4))
}
if length > 0 {
a := uint64(s[0])
b := uint64(s[length>>1])
c := uint64(s[length-1])
y := a + (b << 8)
z := uint64(length) + (c << 2)
return shiftMix(y*k2^z*k3) * k2
}
return k2
}
func hashLen17to32(s []byte) uint64 {
length := len(s)
a := fetch64(s, 0) * k1
b := fetch64(s, 8)
c := fetch64(s, length-8) * k2
d := fetch64(s, length-16) * k0
return hashLen16(rotate(a-b, 43)+rotate(c, 30)+d, a+rotate(b^k3, 20)-c+uint64(length))
}
func weakHashLen32WithSeeds(w, x, y, z, a, b uint64) uint128 {
a += w
b = rotate(b+a+z, 21)
c := a
a += x
a += y
b += rotate(a, 44)
return uint128{first: a + z, second: b + c}
}
func weakHashLen32WithSeedsFromArray(s []byte, offset int, a, b uint64) uint128 {
return weakHashLen32WithSeeds(
fetch64(s, offset),
fetch64(s, offset+8),
fetch64(s, offset+16),
fetch64(s, offset+24),
a,
b,
)
}
func hashLen33to64(s []byte) uint64 {
length := len(s)
z := fetch64(s, 24)
a := fetch64(s, 0) + (uint64(length)+fetch64(s, length-16))*k0
b := rotate(a+z, 52)
c := rotate(a, 37)
a += fetch64(s, 8)
c += rotate(a, 7)
a += fetch64(s, 16)
vf := a + z
vs := b + rotate(a, 31) + c
a = fetch64(s, 16) + fetch64(s, length-32)
z2 := fetch64(s, length-8)
b = rotate(a+z2, 52)
c = rotate(a, 37)
a += fetch64(s, length-24)
c += rotate(a, 7)
a += fetch64(s, length-16)
wf := a + z2
ws := b + rotate(a, 31) + c
r := shiftMix((vf+ws)*k2 + (wf+vs)*k0)
return shiftMix(r*k0+vs) * k2
}
func cityHash64(data []byte) uint64 {
length := len(data)
if length <= 32 {
if length <= 16 {
return hashLen0to16(data)
}
return hashLen17to32(data)
}
if length <= 64 {
return hashLen33to64(data)
}
x := fetch64(data, 0)
y := fetch64(data, length-16) ^ k1
z := fetch64(data, length-56) ^ k0
v := weakHashLen32WithSeedsFromArray(data, length-64, uint64(length), y)
w := weakHashLen32WithSeedsFromArray(data, length-32, uint64(length)*k1, k0)
z += shiftMix(v.second) * k1
x = rotate(z+x, 39) * k1
y = rotate(y, 33) * k1
currentLen := (length - 1) &^ 63
offset := 0
for currentLen > 0 {
x = rotate(x+y+v.first+fetch64(data, offset+16), 37) * k1
y = rotate(y+v.second+fetch64(data, offset+48), 42) * k1
x ^= w.second
y ^= v.first
z = rotate(z^w.first, 33)
v = weakHashLen32WithSeedsFromArray(data, offset, v.second*k1, x+w.first)
w = weakHashLen32WithSeedsFromArray(data, offset+32, z+w.second, y)
z, x = x, z
offset += 64
currentLen -= 64
}
return hashLen16(hashLen16(v.first, w.first)+shiftMix(y)*k1+z, hashLen16(v.second, w.second)+x)
}
func cityHash64Text(text string) string {
value := cityHash64([]byte(text))
return strconv.FormatUint(value, 10)
}
func cityHash64File(path string) (string, error) {
data, err := os.ReadFile(path)
if err != nil {
return "", err
}
value := cityHash64(data)
return strconv.FormatUint(value, 10), nil
}
func main() {
fmt.Println("cityhash64=", cityHash64Text("hello"))
file, err := os.CreateTemp("", "cityhash-example-*.bin")
if err != nil {
panic(err)
}
defer os.Remove(file.Name())
file.WriteString("hello")
file.Close()
fileHash, err := cityHash64File(file.Name())
if err != nil {
panic(err)
}
fmt.Println("cityhash64(file)=", fileHash)
}