Go (golang) implementation of http://www.hashids.org

go-hashids Build Status GoDoc

Go (golang) v1 implementation of http://www.hashids.org under MIT License (same as the original implementations)

Original implementations by Ivan Akimov

Setup

go get github.com/speps/go-hashids

CLI tool :

go get github.com/speps/go-hashids/cmd/hashid

Example

package main

import "fmt"
import "github.com/speps/go-hashids"

func main() {
	hd := hashids.NewData()
	hd.Salt = "this is my salt"
	hd.MinLength = 30
	h, _ := hashids.NewWithData(hd)
	e, _ := h.Encode([]int{45, 434, 1313, 99})
	fmt.Println(e)
	d, _ := h.DecodeWithError(e)
	fmt.Println(d)
}

Thanks to all the contributors

Let me know if I forgot anyone of course.

Changelog

2017/05/09

  • Changed API
    • New methods now return errors
    • Added sanity check in Decode that makes sure that the salt is consistent

2014/09/13

  • Updated to Hashids v1.0.0 (should be compatible with other implementations, let me know if not, was checked against the Javascript version)
  • Changed API
    • Encrypt/Decrypt are now Encode/Decode
    • HashID is now constructed from HashIDData containing alphabet, salt and minimum length
Comments
  • Create v2.0.1, a valid go module version

    Create v2.0.1, a valid go module version

    Tag v2.0.0 exists, but it is not valid to make a clean Go module version: v2.0.0 is listed as "incompatible".

    Here is the process to create a v2.0.1 that would fix the problem:

    1. Fix the module go.mod to add a /v2 suffix
    2. Tag v2.0.1
    sed -i '' '1s!.*!module github.com/speps/go-hashids/v2!' go.mod
    git add go.mod
    git commit -m "Fix go module to add /v2 suffix #57"
    git tag v2.0.1
    git push origin v2.0.1
    
  • Use int64 instead of int for numbers.

    Use int64 instead of int for numbers.

    Currently it's impossible to safely Encode/Decode int64 IDs unless all involved systems run on a 64bit machine where int data type is 64-bit. Hashids libraries in other languages (checked C#, JS) seem to support 64bit IDs.

    This PR changes the []int to []int64 everywhere. All tests pass. However, since it changes the signature of the Encode/Decode functions all users of this library have to migrate their code manually.

  • WIP: Pre-allocate buffers, fix go 1.10 compile issues

    WIP: Pre-allocate buffers, fix go 1.10 compile issues

    • Fix building hashid command line
    • Fix go 1.10 warning about Error vs. Errorf
    • Remove unused function
    • Reduce memory allocations in tests by over half, greatly reducing allocations per encode and decode, significantly reducing amount of garbage which collects

    Memory usage of go-hashids.test

    go test -memprofile mem.out -test.memprofilerate=1
    go tool pprof --alloc_space go-hashids.test mem.out
    

    before: 1314.59kB

    after: 592.42kB

  • Not compatible with JS/PHP version

    Not compatible with JS/PHP version

    If you use the Salt like "\xcb\x91\x96\xd0\xa7\x36\x91\x5b\xbf\xd4" the output of both the JS and PHP version is the same (haven't tested other libraries) but the output of his library is completely different

  • Uint32 and Uint64 version

    Uint32 and Uint64 version

    Will there be a UInt32 and UInt64 version for these:

    func (h *HashID) Encode(numbers []int) (string, error) func (h *HashID) EncodeInt64(numbers []int64) (string, error)

    Obviously it may create incompatibilities with eg PHP version of library but for some people that is irrelevant.

  • Reduce allocations to improve performance

    Reduce allocations to improve performance

    hashids is in the middle of a fairly performance sensitive bit of code where I work (Returning thousands of search results, each result id gets encoded). The allocations which happen end up taking a significant amount of the time, so this PR works to reduce the number of allocations per execution from 31 + varying based on the input data to 5 always, while trying to keep the code reasonable to read / work through. The company's code using this doesn't use MinLength, so that I haven't spent a lot of time optimizing, and has more allocations which could probably be removed (Although less than it used to). There is a test added which should make it easier for someone to improve if they want down the line, as well as make sure it doesn't regress.

    Overall:

    • EncodeInt64 allocations reduced from 31 to 5
    • DecodeInt64WithError allocations reduced from 21 to 11 when there is a salt and MinLength isn't specified for single-int64 encodings
  • DecodingWithError does not produce error

    DecodingWithError does not produce error

    Using TestDecodeWithError on https://github.com/speps/go-hashids/blob/master/hashids_test.go#L163 I noticed that it fails and no error is produced if I do the following:

    hdata.Alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"
    dec, err := hid.DecodeWithError("")
    

    However if I use hdata.Alphabet = "PleasAkMEFoThStx" that is currently in the test it works. Depending on the hash dec is either [] or [some number].

    My expectation here was to see an error and [].

  • Fix for #28 just broke MinLength

    Fix for #28 just broke MinLength

    This should not fail, and it never used to, but now it does. The hashid with min length 20 fails to decode the encoded string of length 30.

    func TestHashids(t *testing.T) {
    
    	// MinLength 30
    	hData30 := hashids.NewData()
    	hData30.Salt = "blarg123"
    	hData30.MinLength = 30
    	h30, err := hashids.NewWithData(hData30)
    	if err != nil {
    		t.Error(err)
    	}
    
    	encoded30, err := h30.EncodeInt64([]int64{4})
    	if err != nil {
    		t.Error(err)
    	}
    	decoded30, err := h30.DecodeInt64WithError(encoded30)
    	if err != nil {
    		t.Error(err)
    	}
    	if len(decoded30) != 1 || decoded30[0] != []int64{4}[0] {
    		t.Error("Expected: ", []int64{4}, "; Got: ", decoded30)
    	}
    
    	// Same hashid, but minLength 20
    	hData20 := hashids.NewData()
    	hData20.Salt = "blarg123"
    	hData20.MinLength = 20
    	h20, err := hashids.NewWithData(hData20)
    	if err != nil {
    		t.Error(err)
    	}
    
    	// Should still be able to decode, as the only change is MinLength
    	decoded20, err := h20.DecodeInt64WithError(encoded30)
    	if err != nil {
    		t.Error(err)
    	}
    	if len(decoded20) != 1 || decoded20[0] != []int64{4}[0] {
    		t.Error("Expected: ", []int64{4}, "; Got: ", decoded20)
    	}
    }
    
  • Minimum Alphabet Length

    Minimum Alphabet Length

    What is the consequence of changing the minimum alphabet length to 10.

    I want my alphabet to be "0123456789"?

    I changed your code. I only want to encode numbers and it seems to work.

  • Decode shouldn't panic

    Decode shouldn't panic

    Hashed ids are often used as part of urls. They are outside of program's control (e.g. a user on the website might manually modify url).

    If such modified value is passed to Decode(), it'll panic, which is against Go conventions, see http://blog.golang.org/defer-panic-and-recover:

    The convention in the Go libraries is that even when a package uses panic internally, its external API still presents explicit error return values.

    It would be better if it was Decode(hash string) ([]int, error).

    This would require breaking the API, which might not be a good idea, so an alternative would be to provide additional DecodeSafe (not a great name) or IsValid(hash string) bool so that the string can be checked for correctness before calling Decode().

  • Fix offset panic with smaller results than minLength

    Fix offset panic with smaller results than minLength

    Running the following code you end up with an index out of range panic:

    package main
    
    import hashids "github.com/speps/go-hashids"
    
    func main() {
        hd := hashids.NewData()
        hd.Salt = "salt1"
        hd.MinLength = 10
        h := hashids.NewWithData(hd)
        h.Encode([]int{0})
    }
    
    panic: runtime error: index out of range
    
    goroutine 16 [running]:
    runtime.panic(0x311a0, 0x5e67c)
        /usr/local/Cellar/go/1.3.1/libexec/src/pkg/runtime/panic.c:279 +0xf5
    github.com/speps/go-hashids.(*HashID).Encode(0x2080b6000, 0x2208239ef8, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0)
        /Volumes/CaseSensitive/go/src/github.com/speps/go-hashids/hashids.go:172 +0x11fa
    main.main()
        /private/tmp/hashids.go:14 +0xd5
    
    goroutine 17 [runnable]:
    runtime.MHeap_Scavenger()
        /usr/local/Cellar/go/1.3.1/libexec/src/pkg/runtime/mheap.c:507
    runtime.goexit()
        /usr/local/Cellar/go/1.3.1/libexec/src/pkg/runtime/proc.c:1445
    
    goroutine 18 [runnable]:
    bgsweep()
        /usr/local/Cellar/go/1.3.1/libexec/src/pkg/runtime/mgc0.c:1976
    runtime.goexit()
        /usr/local/Cellar/go/1.3.1/libexec/src/pkg/runtime/proc.c:1445
    

    As far as I can tell, when the second guard character is appended to the result an index offset larger than the length of result is used. Might be worth adding a regression test for this as well.

    Thanks, Adrian

  • Update doc comments

    Update doc comments

    The documentation for the DecodeWithError functions currently don't reflect what the code actually does. When using DecodeWithError with a different MinLength the sanity check will fail, had to look at the actual code to figure out why that is happening because the comment said that MinLength has no effect, which is not correct.

    The PR fixes the comments and mentions the sanity check which is done by the functions.

  • Fix EncodeHex and DecodeHex from original implementations

    Fix EncodeHex and DecodeHex from original implementations

    Hi in original implementation encode the hex 5a74d76ac89b05000e977baa with salt this is my salt is equal with bv89jEY45DslgBOeD2Qg. but i tested it with this repo and it's different with original implementation. i fixed it in this PR.

  • Added new Example in readme for setting alphabet to be used instead of DefaultAlphabet

    Added new Example in readme for setting alphabet to be used instead of DefaultAlphabet

    Due to lack of any example available on the web for changing Alphabet string to be used instead of DefaultAlphabet, I had to read the code files to understand this. I have added a new example so its easier for other users to figure this out.

A golang implementation of Norvig's segmenter

A Go language implementation of the Norvig segmenter, given in this pdf. Licensed WTFPL; please use this code in any way you would like. func MakeWord

Sep 14, 2020
RFC 4566 SDP implementation in go

SDP Package sdp implements SDP: Session Description Protocol [RFC4566]. Complies to gortc principles as core package. Examples See examples folder. Al

Nov 9, 2022
Go implementation of the bspatch algorithm

binarydist Package binarydist implements binary diff and patch as described on http://www.daemonology.net/bsdiff/. It reads and writes files compatibl

Nov 20, 2022
Templating system for HTML and other text documents - go implementation

FAQ What is Kasia.go? Kasia.go is a Go implementation of the Kasia templating system. Kasia is primarily designed for HTML, but you can use it for any

Mar 15, 2022
A diff3 text merge implementation in Go

Diff3 A diff3 text merge implementation in Go based on the awesome paper below. "A Formal Investigation of Diff3" by Sanjeev Khanna, Keshav Kunal, and

Nov 5, 2022
Fastest levenshtein implementation in Go.

fast-levenshtein ?? Fastest levenshtein implementation in Go. Measure the difference between two strings. note: this implementation is currently not t

Dec 20, 2022
[Crawler/Scraper for Golang]🕷A lightweight distributed friendly Golang crawler framework.一个轻量的分布式友好的 Golang 爬虫框架。

Goribot 一个分布式友好的轻量的 Golang 爬虫框架。 完整文档 | Document !! Warning !! Goribot 已经被迁移到 Gospider|github.com/zhshch2002/gospider。修复了一些调度问题并分离了网络请求部分到另一个仓库。此仓库会继续

Oct 29, 2022
golang 在线预览word,excel,pdf,MarkDown(Online Preview Word,Excel,PPT,PDF,Image by Golang)
golang 在线预览word,excel,pdf,MarkDown(Online Preview Word,Excel,PPT,PDF,Image by Golang)

Go View File 在线体验地址 http://39.97.98.75:8082/view/upload (不会经常更新,保留最基本的预览功能。服务器配置较低,如果出现链接超时请等待几秒刷新重试,或者换Chrome) 目前已经完成 docker部署 (不用为运行环境烦恼) Wor

Dec 26, 2022
bluemonday: a fast golang HTML sanitizer (inspired by the OWASP Java HTML Sanitizer) to scrub user generated content of XSS

bluemonday bluemonday is a HTML sanitizer implemented in Go. It is fast and highly configurable. bluemonday takes untrusted user generated content as

Jan 4, 2023
Elegant Scraper and Crawler Framework for Golang

Colly Lightning Fast and Elegant Scraping Framework for Gophers Colly provides a clean interface to write any kind of crawler/scraper/spider. With Col

Dec 30, 2022
A golang package to work with Decentralized Identifiers (DIDs)

did did is a Go package that provides tools to work with Decentralized Identifiers (DIDs). Install go get github.com/ockam-network/did Example packag

Nov 25, 2022
wcwidth for golang

go-runewidth Provides functions to get fixed width of the character or string. Usage runewidth.StringWidth("つのだ☆HIRO") == 12 Author Yasuhiro Matsumoto

Dec 11, 2022
Parses the Graphviz DOT language in golang

Parses the Graphviz DOT language and creates an interface, in golang, with which to easily create new and manipulate existing graphs which can be writ

Dec 25, 2022
Go (Golang) GNU gettext utilities package

Gotext GNU gettext utilities for Go. Features Implements GNU gettext support in native Go. Complete support for PO files including: Support for multil

Dec 18, 2022
htmlquery is golang XPath package for HTML query.

htmlquery Overview htmlquery is an XPath query package for HTML, lets you extract data or evaluate from HTML documents by an XPath expression. htmlque

Jan 4, 2023
omniparser: a native Golang ETL streaming parser and transform library for CSV, JSON, XML, EDI, text, etc.
omniparser: a native Golang ETL streaming parser and transform library for CSV, JSON, XML, EDI, text, etc.

omniparser Omniparser is a native Golang ETL parser that ingests input data of various formats (CSV, txt, fixed length/width, XML, EDI/X12/EDIFACT, JS

Jan 4, 2023
Pagser is a simple, extensible, configurable parse and deserialize html page to struct based on goquery and struct tags for golang crawler
Pagser is a simple, extensible, configurable parse and deserialize html page to struct based on goquery and struct tags for golang crawler

Pagser Pagser inspired by page parser。 Pagser is a simple, extensible, configurable parse and deserialize html page to struct based on goquery and str

Dec 13, 2022
iTunes and RSS 2.0 Podcast Generator in Golang

podcast Package podcast generates a fully compliant iTunes and RSS 2.0 podcast feed for GoLang using a simple API. Full documentation with detailed ex

Dec 23, 2022
TOML parser for Golang with reflection.

THIS PROJECT IS UNMAINTAINED The last commit to this repo before writing this message occurred over two years ago. While it was never my intention to

Dec 30, 2022