10 Favorite Go Libraries for Working with UUIDs

In today's post we will learn about 10 Favorite Go Libraries for Working with UUIDs.

What is a UUID?

A UUID – that’s short for Universally Unique IDentifier, by the way – is a 36-character alphanumeric string that can be used to identify information (such as a table row).

Here is one example of a UUID: acde070d-8c4c-4f0d-9d8a-162843c10333

UUIDs are widely used in part because they are highly likely to be unique globally, meaning that not only is our row’s UUID unique in our database table, it’s probably the only row with that UUID in any system anywhere.

(Technically, it’s not impossible that the same UUID we generate could be used somewhere else, but with 340,282,366,920,938,463,463,374,607,431,768,211,456 different possible UUIDs out there, the chances are very slim).

Table of contents:

  • Goid - Generate and Parse RFC4122 compliant V4 UUIDs.
  • Gouid - Generate cryptographically secure random string IDs with just one allocation.
  • Nanoid - A tiny and efficient Go unique string ID generator.
  • SNO - Compact, sortable and fast unique IDs with embedded metadata.
  • Ulid - Go implementation of ULID (Universally Unique Lexicographically Sortable Identifier).
  • Xid - Xid is a globally unique id generator library, ready to be safely used directly in your server code.
  • Uuid - Generate, encode, and decode UUIDs v1 with fast or cryptographic-quality random node identifier.
  • Uuid - Implementation of Universally Unique Identifier (UUID). Supports both creation and parsing of UUIDs. Actively maintained fork of satori uuid.
  • Uuid - Go package for UUIDs based on RFC 4122 and DCE 1.1: Authentication and Security Services.
  • Wuid - An extremely fast unique number generator, 10-135 times faster than UUID.

1 - Goid:

Generate and Parse RFC4122 compliant V4 UUIDs.

Usage

An example of generating a v4 UUID and outputting it

import (
    "fmt"
    "github.com/jakehl/goid"
)

func main() {
    v4UUID := goid.NewV4UUID()
    fmt.Println(v4UUID)
}

Todo

  •  Add optimised bulk UUID generation

Documentation

The API docs can be viewed here or generated with godoc.

View on Github

2 - Gouid:

Generate cryptographically secure random string IDs with just one allocation.

Gouid - Use Gouid to create cryptographically secure random IDs. IDs can be byte slices or strings, both generated with just one allocation (see benchmarks below).

Example

package main

import (
	"fmt"
	
	"github.com/twharmon/gouid"
)

func main() {
	a := gouid.String(8, gouid.LowerCaseAlphaNum)
	fmt.Println(a) // mp6nq37p

	b := gouid.String(16, gouid.MixedCaseAlpha)
	fmt.Println(b) // hCSoemLKaUQtoXgh

	c := gouid.Bytes(16)
	fmt.Println(c) // [244 188 217 137 122 245 94 126 80 119 87 170 6 178 228 179]
}

Benchmarks

BenchmarkString8	120 ns/op	       8 B/op	       1 allocs/op
BenchmarkString16	197 ns/op	      16 B/op	       1 allocs/op
BenchmarkString32	345 ns/op	      32 B/op	       1 allocs/op
BenchmarkBytes8	 	67.3 ns/op	       8 B/op	       1 allocs/op
BenchmarkBytes16	94.4 ns/op	      16 B/op	       1 allocs/op
BenchmarkBytes32	143 ns/op	      32 B/op	       1 allocs/op

Contribute

Make a pull request.

View on Github

3 - Nanoid:

A tiny and efficient Go unique string ID generator.

A tiny and fast Go unique string generator

  • Safe. It uses cryptographically strong random APIs and tests distribution of symbols.
  • Compact. It uses a larger alphabet than UUID (A-Za-z0-9_-). So ID size was reduced from 36 to 21 symbols.
id, err := nanoid.New() //> "i25_rX9zwDdDn7Sg-ZoaH"
if err != nil {
    log.Fatalln(err)
}

Installation

Once Go is installed, run the following command to get Nano ID.

go get github.com/aidarkhanov/nanoid/v2

Documentation

The package reference is located at pkg.go.dev/github.com/aidarkhanov/nanoid/v2.

Roadmap

  • The API of this package is frozen.
  • Release patches if necessary.

View on Github

4 - SNO:

Compact, sortable and fast unique IDs with embedded metadata.

A spec for unique IDs in distributed systems based on the Snowflake design, i.e. a coordination-based ID variant. It aims to be friendly to both machines and humans, compact, versatile and fast.

This repository contains a Go package for generating such IDs.

Features

  • Compact - 10 bytes in its binary representation, canonically encoded as 16 characters.
    URL-safe and non-ambiguous encoding which also happens to be at the binary length of UUIDs - snos can be stored as UUIDs in your database of choice.
  • K-sortable in either representation.
  • Embedded timestamp with a 4msec resolution, bounded within the years 2010 - 2079.
    Handles clock drifts gracefully, without waiting.
  • Embedded byte for arbitrary data.
  • Simple data layout - straightforward to inspect or encode/decode.
  • Optional and flexible configuration and coordination.
  • Fast, wait-free, safe for concurrent use.
    Clocks in at about 500 LoC, has no external dependencies and minimal dependencies on std.
  • ‭A pool of ≥ 16,384,000 IDs per second.
    65,536 guaranteed unique IDs per 4msec per partition (65,536 combinations) per metabyte (256 combinations) per tick-tock (1 bit adjustment for clock drifts). 549,755,813,888,000 is the global pool per second when all components are taken into account.

Non-features / cons

  • True randomness. snos embed a counter and have no entropy. They are not suitable in a context where unpredictability of IDs is a must. They still, however, meet the common requirement of keeping internal counts (e.g. total number of entitites) unguessable and appear obfuscated;
  • Time precision. While good enough for many use cases, not quite there for others. The ➜ Metabyte can be used to get around this limitation, however.
  • It's 10 bytes, not 8. This is suboptimal as far as memory alignment is considered (platform dependent).

Usage (➜ API)

sno comes with a package-level generator on top of letting you configure your own generators.

Generating a new ID using the defaults takes no more than importing the package and:

id := sno.New(0)

Where 0 is the ➜ Metabyte.
 

The global generator is immutable and private. It's therefore also not possible to restore it using a Snapshot. Its Partition is based on time and changes across restarts.

Partitions (➜ doc)

As soon as you run more than 1 generator, you should start coordinating the creation of Generators to actually guarantee a collision-free ride. This applies to all specs of the Snowflake variant.

Partitions are one of several friends you have to get you those guarantees. A Partition is 2 bytes. What they mean and how you define them is up to you.

generator, err := sno.NewGenerator(&sno.GeneratorSnapshot{
	Partition: sno.Partition{'A', 10}
}, nil)

Multiple generators can share a partition by dividing the sequence pool between them (➜ Sequence sharding).

Snapshots (➜ doc)

Snapshots happen to serve both as configuration and a means of saving and restoring generator data. They are optional - simply pass nil to NewGenerator(), to get a Generator with sane defaults and a unique (in-process) Partition.

Snapshots can be taken at runtime:

s := generator.Snapshot()

This exposes most of a Generator's internal bookkeeping data. In an ideal world where programmers are not lazy until their system runs into an edge case - you'd persist that snapshot across restarts and restore generators instead of just creating them from scratch each time. This will keep you safe both if a large clock drift happens during the restart -- or before, and you just happen to come back online again "in the past", relative to IDs that had already been generated.

A snapshot is a sample in time - it will very quickly get stale. Only take snapshots meant for restoring them later when generators are already offline - or for metrics purposes when online.

View on Github

5 - Ulid:

Go implementation of ULID (Universally Unique Lexicographically Sortable Identifier).

Background

A GUID/UUID can be suboptimal for many use-cases because:

  • It isn't the most character efficient way of encoding 128 bits
  • UUID v1/v2 is impractical in many environments, as it requires access to a unique, stable MAC address
  • UUID v3/v5 requires a unique seed and produces randomly distributed IDs, which can cause fragmentation in many data structures
  • UUID v4 provides no other information than randomness which can cause fragmentation in many data structures

A ULID however:

  • Is compatible with UUID/GUID's
  • 1.21e+24 unique ULIDs per millisecond (1,208,925,819,614,629,174,706,176 to be exact)
  • Lexicographically sortable
  • Canonically encoded as a 26 character string, as opposed to the 36 character UUID
  • Uses Crockford's base32 for better efficiency and readability (5 bits per character)
  • Case insensitive
  • No special characters (URL safe)
  • Monotonic sort order (correctly detects and handles the same millisecond)

Install

This package requires Go modules.

go get github.com/oklog/ulid/v2

Usage

ULIDs are constructed from two things: a timestamp with millisecond precision, and some random data.

Timestamps are modeled as uint64 values representing a Unix time in milliseconds. They can be produced by passing a time.Time to ulid.Timestamp, or by calling time.Time.UnixMilli and converting the returned value to uint64.

Random data is taken from a provided io.Reader. This design allows for greater flexibility when choosing trade-offs, but can be a bit confusing to newcomers.

If you just want to generate a ULID and don't (yet) care about details like performance, cryptographic security, monotonicity, etc., use the ulid.Make helper function. This function calls time.Now to get a timestamp, and uses a source of entropy which is process-global, pseudo-random), and monotonic).

println(ulid.Make())
// 01G65Z755AFWAKHE12NY0CQ9FH

More advanced use cases should utilize ulid.New.

entropy := rand.New(rand.NewSource(time.Now().UnixNano()))
ms := ulid.Timestamp(time.Now())
println(ulid.New(ms, entropy))
// 01G65Z755AFWAKHE12NY0CQ9FH

Care should be taken when providing a source of entropy.

The above example utilizes math/rand.Rand, which is not safe for concurrent use by multiple goroutines. Consider alternatives such as x/exp/rand. Security-sensitive use cases should always use cryptographically secure entropy provided by crypto/rand.

Performance-sensitive use cases should avoid synchronization when generating IDs. One option is to use a unique source of entropy for each concurrent goroutine, which results in no lock contention, but cannot provide strong guarantees about the random data, and does not provide monotonicity within a given millisecond. One common performance optimization is to pool sources of entropy using a sync.Pool.

Monotonicity is a property that says each ULID is "bigger than" the previous one. ULIDs are automatically monotonic, but only to millisecond precision. ULIDs generated within the same millisecond are ordered by their random component, which means they are by default un-ordered. You can use ulid.MonotonicEntropy or ulid.LockedMonotonicEntropy to create ULIDs that are monotonic within a given millisecond, with caveats. See the documentation for details.

If you don't care about time-based ordering of generated IDs, then there's no reason to use ULIDs! There are many other kinds of IDs that are easier, faster, smaller, etc. Consider UUIDs.

View on Github

6 - Xid:

Xid is a globally unique id generator library, ready to be safely used directly in your server code.

Package xid is a globally unique id generator library, ready to safely be used directly in your server code.

Xid uses the Mongo Object ID algorithm to generate globally unique ids with a different serialization (base64) to make it shorter when transported as a string: https://docs.mongodb.org/manual/reference/object-id/

  • 4-byte value representing the seconds since the Unix epoch,
  • 3-byte machine identifier,
  • 2-byte process id, and
  • 3-byte counter, starting with a random value.

The binary representation of the id is compatible with Mongo 12 bytes Object IDs. The string representation is using base32 hex (w/o padding) for better space efficiency when stored in that form (20 bytes). The hex variant of base32 is used to retain the sortable property of the id.

Xid doesn't use base64 because case sensitivity and the 2 non alphanum chars may be an issue when transported as a string between various systems. Base36 wasn't retained either because 1/ it's not standard 2/ the resulting size is not predictable (not bit aligned) and 3/ it would not remain sortable. To validate a base32 xid, expect a 20 chars long, all lowercase sequence of a to v letters and 0 to 9 numbers ([0-9a-v]{20}).

UUIDs are 16 bytes (128 bits) and 36 chars as string representation. Twitter Snowflake ids are 8 bytes (64 bits) but require machine/data-center configuration and/or central generator servers. xid stands in between with 12 bytes (96 bits) and a more compact URL-safe string representation (20 chars). No configuration or central generator server is required so it can be used directly in server's code.

Install

go get github.com/rs/xid

Usage

guid := xid.New()

println(guid.String())
// Output: 9m4e2mr0ui3e8a215n4g

Get xid embedded info:

guid.Machine()
guid.Pid()
guid.Time()
guid.Counter()

Benchmark

Benchmark against Go Maxim Bublis's UUID.

BenchmarkXID        	20000000	        91.1 ns/op	      32 B/op	       1 allocs/op
BenchmarkXID-2      	20000000	        55.9 ns/op	      32 B/op	       1 allocs/op
BenchmarkXID-4      	50000000	        32.3 ns/op	      32 B/op	       1 allocs/op
BenchmarkUUIDv1     	10000000	       204 ns/op	      48 B/op	       1 allocs/op
BenchmarkUUIDv1-2   	10000000	       160 ns/op	      48 B/op	       1 allocs/op
BenchmarkUUIDv1-4   	10000000	       195 ns/op	      48 B/op	       1 allocs/op
BenchmarkUUIDv4     	 1000000	      1503 ns/op	      64 B/op	       2 allocs/op
BenchmarkUUIDv4-2   	 1000000	      1427 ns/op	      64 B/op	       2 allocs/op
BenchmarkUUIDv4-4   	 1000000	      1452 ns/op	      64 B/op	       2 allocs/op

Note: UUIDv1 requires a global lock, hence the performance degradation as we add more CPUs.

View on Github

7 - Uuid:

Generate, encode, and decode UUIDs v1 with fast or cryptographic-quality random node identifier.

Project Status

v1.1.0 Stable: Guaranteed no breaking changes to the API in future v1.x releases. Probably safe to use in production, though provided on "AS IS" basis.

This package is being actively maintained. If you encounter any problems or have any suggestions for improvement, please open an issue. Pull requests are welcome.

Overview

Package uuid implements generation and manipulation of UUIDs (v1 defined in RFC 4122).

Version 1 UUIDs are time-based and include a node identifier that can be a MAC address or a random 48-bit value.

This package uses the random approach for the node identifier, setting both the 'multicast' and 'local' bits to make sure the value cannot be confused with a real IEEE 802 address (see section 4.5 of RFC 4122). The initial node identifier is a cryptographic-quality random 46-bit value. The first 30 bits can be set and retrieved with the SetNodeId and NodeId functions and method, so that they can be used as a hard-coded instance id. The remaining 16 bits are reserved for increasing the randomness of the UUIDs and to avoid collisions on clock sequence rollovers.

The basic generator New increments the clock sequence on every call and when the counter rolls over the last 16 bits of the node identifier are regenerated using a PRNG seeded at init()-time with the initial node identifier. This approach sacrifices cryptographic quality for speed and for avoiding depletion of the OS entropy pool (yes, it can and does happen).

The NewCrypto generator replaces the clock sequence and last 16 bits of the node identifier on each call with cryptographic-quality random values.

Installation

go get github.com/agext/uuid

View on Github

8 - Uuid:

Implementation of Universally Unique Identifier (UUID). Supports both creation and parsing of UUIDs. Actively maintained fork of satori uuid.

Package uuid provides a pure Go implementation of Universally Unique Identifiers (UUID) variant as defined in RFC-4122. This package supports both the creation and parsing of UUIDs in different formats.

This package supports the following UUID versions:

  • Version 1, based on timestamp and MAC address (RFC-4122)
  • Version 3, based on MD5 hashing of a named value (RFC-4122)
  • Version 4, based on random numbers (RFC-4122)
  • Version 5, based on SHA-1 hashing of a named value (RFC-4122)

This package also supports experimental Universally Unique Identifier implementations based on a draft RFC that updates RFC-4122

  • Version 6, a k-sortable id based on timestamp, and field-compatible with v1 (draft-peabody-dispatch-new-uuid-format, RFC-4122)
  • Version 7, a k-sortable id based on timestamp (draft-peabody-dispatch-new-uuid-format, RFC-4122)

The v6 and v7 IDs are not considered a part of the stable API, and may be subject to behavior or API changes as part of minor releases to this package. They will be updated as the draft RFC changes, and will become stable if and when the draft RFC is accepted.

Project History

This project was originally forked from the github.com/satori/go.uuid repository after it appeared to be no longer maintained, while exhibiting critical flaws. We have decided to take over this project to ensure it receives regular maintenance for the benefit of the larger Go community.

We'd like to thank Maxim Bublis for his hard work on the original iteration of the package.

Installation

It is recommended to use a package manager like dep that understands tagged releases of a package, as well as semantic versioning.

If you are unable to make use of a dependency manager with your project, you can use the go get command to download it directly:

$ go get github.com/gofrs/uuid

Requirements

Due to subtests not being supported in older versions of Go, this package is only regularly tested against Go 1.7+. This package may work perfectly fine with Go 1.2+, but support for these older versions is not actively maintained.

Go 1.11 Modules

As of v3.2.0, this repository no longer adopts Go modules, and v3.2.0 no longer has a go.mod file. As a result, v3.2.0 also drops support for the github.com/gofrs/uuid/v3 import path. Only module-based consumers are impacted. With the v3.2.0 release, all gofrs/uuid consumers should use the github.com/gofrs/uuid import path.

An existing module-based consumer will continue to be able to build using the github.com/gofrs/uuid/v3 import path using any valid consumer go.mod that worked prior to the publishing of v3.2.0, but any module-based consumer should start using the github.com/gofrs/uuid import path when possible and must use the github.com/gofrs/uuid import path prior to upgrading to v3.2.0.

Please refer to Issue #61 and Issue #66 for more details.

Usage

Here is a quick overview of how to use this package. For more detailed documentation, please see the GoDoc Page.

package main

import (
	"log"

	"github.com/gofrs/uuid"
)

// Create a Version 4 UUID, panicking on error.
// Use this form to initialize package-level variables.
var u1 = uuid.Must(uuid.NewV4())

func main() {
	// Create a Version 4 UUID.
	u2, err := uuid.NewV4()
	if err != nil {
		log.Fatalf("failed to generate UUID: %v", err)
	}
	log.Printf("generated Version 4 UUID %v", u2)

	// Parse a UUID from a string.
	s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
	u3, err := uuid.FromString(s)
	if err != nil {
		log.Fatalf("failed to parse UUID %q: %v", s, err)
	}
	log.Printf("successfully parsed UUID %v", u3)
}

View on Github

9 - Uuid:

Go package for UUIDs based on RFC 4122 and DCE 1.1: Authentication and Security Services.

The uuid package generates and inspects UUIDs based on RFC 4122 and DCE 1.1: Authentication and Security Services.

This package is based on the github.com/pborman/uuid package (previously named code.google.com/p/go-uuid). It differs from these earlier packages in that a UUID is a 16 byte array rather than a byte slice. One loss due to this change is the ability to represent an invalid UUID (vs a NIL UUID).

Install

go get github.com/google/uuid

Documentation

Full go doc style documentation for the package can be viewed online without installing this package by using the GoDoc site here: http://pkg.go.dev/github.com/google/uuid

View on Github

10 - Wuid:

An extremely fast unique number generator, 10-135 times faster than UUID.

Overview

  • WUID is a globally unique number generator, while it is NOT a UUID implementation.
  • WUID is 10-135 times faster than UUID and 4600 times faster than generating unique numbers with Redis.
  • Each WUID instance generates unique 64-bit integers in sequence. The high 28 bits are loaded from a data store. By now, Redis, MySQL, MongoDB and Callback are supported.

Benchmarks

BenchmarkWUID       187500764            6.38 ns/op        0 B/op          0 allocs/op
BenchmarkRand       97180698            12.2 ns/op         0 B/op          0 allocs/op
BenchmarkTimestamp  17126514            67.8 ns/op         0 B/op          0 allocs/op
BenchmarkUUID_V1    11986558            99.6 ns/op         0 B/op          0 allocs/op
BenchmarkUUID_V2    12017754           101 ns/op           0 B/op          0 allocs/op
BenchmarkUUID_V3     4925020           242 ns/op         144 B/op          4 allocs/op
BenchmarkUUID_V4    14184271            84.1 ns/op        16 B/op          1 allocs/op
BenchmarkUUID_V5     4277338           274 ns/op         176 B/op          4 allocs/op
BenchmarkRedis         35462         35646 ns/op         176 B/op          5 allocs/op
BenchmarkSnowflake   4931476           244 ns/op           0 B/op          0 allocs/op
BenchmarkULID        8410358           141 ns/op          16 B/op          1 allocs/op
BenchmarkXID        15000969            79.2 ns/op         0 B/op          0 allocs/op
BenchmarkShortID     1738039           698.9 ns/op       311 B/op         11 allocs/op

Features

  • Extremely fast
  • Thread-safe
  • Being unique across time
  • Being unique within a data center
  • Being unique globally if all data centers share a same data store, or they use different section IDs
  • Being capable of generating 100M unique numbers in a single second with each WUID instance
  • Auto-renew when the low 36 bits are about to run out

Install

go get -u github.com/edwingeng/wuid

Usage examples

Redis

import "github.com/edwingeng/wuid/redis/wuid"

newClient := func() (redis.Cmdable, bool, error) {
    var client redis.Cmdable
    // ...
    return client, true, nil
}

// Setup
g := NewWUID("default", nil)
_ = g.LoadH28FromRedis(newClient, "wuid")

// Generate
for i := 0; i < 10; i++ {
    fmt.Printf("%#016x\n", g.Next())
}

MySQL

import "github.com/edwingeng/wuid/mysql/wuid"

newDB := func() (*sql.DB, bool, error) {
    var db *sql.DB
    // ...
    return db, true, nil
}

// Setup
g := NewWUID("default", nil)
_ = g.LoadH28FromMysql(newDB, "wuid")

// Generate
for i := 0; i < 10; i++ {
    fmt.Printf("%#016x\n", g.Next())
}

View on Github

Thank you for following this article.

Related videos:

Universally Unique Identifiers (UUID/GUID) // Game Engine series

#go #golang #uuid 

What is GEEK

Buddha Community

10 Favorite Go Libraries for Working with UUIDs

10 Favorite Go Libraries for Working with UUIDs

In today's post we will learn about 10 Favorite Go Libraries for Working with UUIDs.

What is a UUID?

A UUID – that’s short for Universally Unique IDentifier, by the way – is a 36-character alphanumeric string that can be used to identify information (such as a table row).

Here is one example of a UUID: acde070d-8c4c-4f0d-9d8a-162843c10333

UUIDs are widely used in part because they are highly likely to be unique globally, meaning that not only is our row’s UUID unique in our database table, it’s probably the only row with that UUID in any system anywhere.

(Technically, it’s not impossible that the same UUID we generate could be used somewhere else, but with 340,282,366,920,938,463,463,374,607,431,768,211,456 different possible UUIDs out there, the chances are very slim).

Table of contents:

  • Goid - Generate and Parse RFC4122 compliant V4 UUIDs.
  • Gouid - Generate cryptographically secure random string IDs with just one allocation.
  • Nanoid - A tiny and efficient Go unique string ID generator.
  • SNO - Compact, sortable and fast unique IDs with embedded metadata.
  • Ulid - Go implementation of ULID (Universally Unique Lexicographically Sortable Identifier).
  • Xid - Xid is a globally unique id generator library, ready to be safely used directly in your server code.
  • Uuid - Generate, encode, and decode UUIDs v1 with fast or cryptographic-quality random node identifier.
  • Uuid - Implementation of Universally Unique Identifier (UUID). Supports both creation and parsing of UUIDs. Actively maintained fork of satori uuid.
  • Uuid - Go package for UUIDs based on RFC 4122 and DCE 1.1: Authentication and Security Services.
  • Wuid - An extremely fast unique number generator, 10-135 times faster than UUID.

1 - Goid:

Generate and Parse RFC4122 compliant V4 UUIDs.

Usage

An example of generating a v4 UUID and outputting it

import (
    "fmt"
    "github.com/jakehl/goid"
)

func main() {
    v4UUID := goid.NewV4UUID()
    fmt.Println(v4UUID)
}

Todo

  •  Add optimised bulk UUID generation

Documentation

The API docs can be viewed here or generated with godoc.

View on Github

2 - Gouid:

Generate cryptographically secure random string IDs with just one allocation.

Gouid - Use Gouid to create cryptographically secure random IDs. IDs can be byte slices or strings, both generated with just one allocation (see benchmarks below).

Example

package main

import (
	"fmt"
	
	"github.com/twharmon/gouid"
)

func main() {
	a := gouid.String(8, gouid.LowerCaseAlphaNum)
	fmt.Println(a) // mp6nq37p

	b := gouid.String(16, gouid.MixedCaseAlpha)
	fmt.Println(b) // hCSoemLKaUQtoXgh

	c := gouid.Bytes(16)
	fmt.Println(c) // [244 188 217 137 122 245 94 126 80 119 87 170 6 178 228 179]
}

Benchmarks

BenchmarkString8	120 ns/op	       8 B/op	       1 allocs/op
BenchmarkString16	197 ns/op	      16 B/op	       1 allocs/op
BenchmarkString32	345 ns/op	      32 B/op	       1 allocs/op
BenchmarkBytes8	 	67.3 ns/op	       8 B/op	       1 allocs/op
BenchmarkBytes16	94.4 ns/op	      16 B/op	       1 allocs/op
BenchmarkBytes32	143 ns/op	      32 B/op	       1 allocs/op

Contribute

Make a pull request.

View on Github

3 - Nanoid:

A tiny and efficient Go unique string ID generator.

A tiny and fast Go unique string generator

  • Safe. It uses cryptographically strong random APIs and tests distribution of symbols.
  • Compact. It uses a larger alphabet than UUID (A-Za-z0-9_-). So ID size was reduced from 36 to 21 symbols.
id, err := nanoid.New() //> "i25_rX9zwDdDn7Sg-ZoaH"
if err != nil {
    log.Fatalln(err)
}

Installation

Once Go is installed, run the following command to get Nano ID.

go get github.com/aidarkhanov/nanoid/v2

Documentation

The package reference is located at pkg.go.dev/github.com/aidarkhanov/nanoid/v2.

Roadmap

  • The API of this package is frozen.
  • Release patches if necessary.

View on Github

4 - SNO:

Compact, sortable and fast unique IDs with embedded metadata.

A spec for unique IDs in distributed systems based on the Snowflake design, i.e. a coordination-based ID variant. It aims to be friendly to both machines and humans, compact, versatile and fast.

This repository contains a Go package for generating such IDs.

Features

  • Compact - 10 bytes in its binary representation, canonically encoded as 16 characters.
    URL-safe and non-ambiguous encoding which also happens to be at the binary length of UUIDs - snos can be stored as UUIDs in your database of choice.
  • K-sortable in either representation.
  • Embedded timestamp with a 4msec resolution, bounded within the years 2010 - 2079.
    Handles clock drifts gracefully, without waiting.
  • Embedded byte for arbitrary data.
  • Simple data layout - straightforward to inspect or encode/decode.
  • Optional and flexible configuration and coordination.
  • Fast, wait-free, safe for concurrent use.
    Clocks in at about 500 LoC, has no external dependencies and minimal dependencies on std.
  • ‭A pool of ≥ 16,384,000 IDs per second.
    65,536 guaranteed unique IDs per 4msec per partition (65,536 combinations) per metabyte (256 combinations) per tick-tock (1 bit adjustment for clock drifts). 549,755,813,888,000 is the global pool per second when all components are taken into account.

Non-features / cons

  • True randomness. snos embed a counter and have no entropy. They are not suitable in a context where unpredictability of IDs is a must. They still, however, meet the common requirement of keeping internal counts (e.g. total number of entitites) unguessable and appear obfuscated;
  • Time precision. While good enough for many use cases, not quite there for others. The ➜ Metabyte can be used to get around this limitation, however.
  • It's 10 bytes, not 8. This is suboptimal as far as memory alignment is considered (platform dependent).

Usage (➜ API)

sno comes with a package-level generator on top of letting you configure your own generators.

Generating a new ID using the defaults takes no more than importing the package and:

id := sno.New(0)

Where 0 is the ➜ Metabyte.
 

The global generator is immutable and private. It's therefore also not possible to restore it using a Snapshot. Its Partition is based on time and changes across restarts.

Partitions (➜ doc)

As soon as you run more than 1 generator, you should start coordinating the creation of Generators to actually guarantee a collision-free ride. This applies to all specs of the Snowflake variant.

Partitions are one of several friends you have to get you those guarantees. A Partition is 2 bytes. What they mean and how you define them is up to you.

generator, err := sno.NewGenerator(&sno.GeneratorSnapshot{
	Partition: sno.Partition{'A', 10}
}, nil)

Multiple generators can share a partition by dividing the sequence pool between them (➜ Sequence sharding).

Snapshots (➜ doc)

Snapshots happen to serve both as configuration and a means of saving and restoring generator data. They are optional - simply pass nil to NewGenerator(), to get a Generator with sane defaults and a unique (in-process) Partition.

Snapshots can be taken at runtime:

s := generator.Snapshot()

This exposes most of a Generator's internal bookkeeping data. In an ideal world where programmers are not lazy until their system runs into an edge case - you'd persist that snapshot across restarts and restore generators instead of just creating them from scratch each time. This will keep you safe both if a large clock drift happens during the restart -- or before, and you just happen to come back online again "in the past", relative to IDs that had already been generated.

A snapshot is a sample in time - it will very quickly get stale. Only take snapshots meant for restoring them later when generators are already offline - or for metrics purposes when online.

View on Github

5 - Ulid:

Go implementation of ULID (Universally Unique Lexicographically Sortable Identifier).

Background

A GUID/UUID can be suboptimal for many use-cases because:

  • It isn't the most character efficient way of encoding 128 bits
  • UUID v1/v2 is impractical in many environments, as it requires access to a unique, stable MAC address
  • UUID v3/v5 requires a unique seed and produces randomly distributed IDs, which can cause fragmentation in many data structures
  • UUID v4 provides no other information than randomness which can cause fragmentation in many data structures

A ULID however:

  • Is compatible with UUID/GUID's
  • 1.21e+24 unique ULIDs per millisecond (1,208,925,819,614,629,174,706,176 to be exact)
  • Lexicographically sortable
  • Canonically encoded as a 26 character string, as opposed to the 36 character UUID
  • Uses Crockford's base32 for better efficiency and readability (5 bits per character)
  • Case insensitive
  • No special characters (URL safe)
  • Monotonic sort order (correctly detects and handles the same millisecond)

Install

This package requires Go modules.

go get github.com/oklog/ulid/v2

Usage

ULIDs are constructed from two things: a timestamp with millisecond precision, and some random data.

Timestamps are modeled as uint64 values representing a Unix time in milliseconds. They can be produced by passing a time.Time to ulid.Timestamp, or by calling time.Time.UnixMilli and converting the returned value to uint64.

Random data is taken from a provided io.Reader. This design allows for greater flexibility when choosing trade-offs, but can be a bit confusing to newcomers.

If you just want to generate a ULID and don't (yet) care about details like performance, cryptographic security, monotonicity, etc., use the ulid.Make helper function. This function calls time.Now to get a timestamp, and uses a source of entropy which is process-global, pseudo-random), and monotonic).

println(ulid.Make())
// 01G65Z755AFWAKHE12NY0CQ9FH

More advanced use cases should utilize ulid.New.

entropy := rand.New(rand.NewSource(time.Now().UnixNano()))
ms := ulid.Timestamp(time.Now())
println(ulid.New(ms, entropy))
// 01G65Z755AFWAKHE12NY0CQ9FH

Care should be taken when providing a source of entropy.

The above example utilizes math/rand.Rand, which is not safe for concurrent use by multiple goroutines. Consider alternatives such as x/exp/rand. Security-sensitive use cases should always use cryptographically secure entropy provided by crypto/rand.

Performance-sensitive use cases should avoid synchronization when generating IDs. One option is to use a unique source of entropy for each concurrent goroutine, which results in no lock contention, but cannot provide strong guarantees about the random data, and does not provide monotonicity within a given millisecond. One common performance optimization is to pool sources of entropy using a sync.Pool.

Monotonicity is a property that says each ULID is "bigger than" the previous one. ULIDs are automatically monotonic, but only to millisecond precision. ULIDs generated within the same millisecond are ordered by their random component, which means they are by default un-ordered. You can use ulid.MonotonicEntropy or ulid.LockedMonotonicEntropy to create ULIDs that are monotonic within a given millisecond, with caveats. See the documentation for details.

If you don't care about time-based ordering of generated IDs, then there's no reason to use ULIDs! There are many other kinds of IDs that are easier, faster, smaller, etc. Consider UUIDs.

View on Github

6 - Xid:

Xid is a globally unique id generator library, ready to be safely used directly in your server code.

Package xid is a globally unique id generator library, ready to safely be used directly in your server code.

Xid uses the Mongo Object ID algorithm to generate globally unique ids with a different serialization (base64) to make it shorter when transported as a string: https://docs.mongodb.org/manual/reference/object-id/

  • 4-byte value representing the seconds since the Unix epoch,
  • 3-byte machine identifier,
  • 2-byte process id, and
  • 3-byte counter, starting with a random value.

The binary representation of the id is compatible with Mongo 12 bytes Object IDs. The string representation is using base32 hex (w/o padding) for better space efficiency when stored in that form (20 bytes). The hex variant of base32 is used to retain the sortable property of the id.

Xid doesn't use base64 because case sensitivity and the 2 non alphanum chars may be an issue when transported as a string between various systems. Base36 wasn't retained either because 1/ it's not standard 2/ the resulting size is not predictable (not bit aligned) and 3/ it would not remain sortable. To validate a base32 xid, expect a 20 chars long, all lowercase sequence of a to v letters and 0 to 9 numbers ([0-9a-v]{20}).

UUIDs are 16 bytes (128 bits) and 36 chars as string representation. Twitter Snowflake ids are 8 bytes (64 bits) but require machine/data-center configuration and/or central generator servers. xid stands in between with 12 bytes (96 bits) and a more compact URL-safe string representation (20 chars). No configuration or central generator server is required so it can be used directly in server's code.

Install

go get github.com/rs/xid

Usage

guid := xid.New()

println(guid.String())
// Output: 9m4e2mr0ui3e8a215n4g

Get xid embedded info:

guid.Machine()
guid.Pid()
guid.Time()
guid.Counter()

Benchmark

Benchmark against Go Maxim Bublis's UUID.

BenchmarkXID        	20000000	        91.1 ns/op	      32 B/op	       1 allocs/op
BenchmarkXID-2      	20000000	        55.9 ns/op	      32 B/op	       1 allocs/op
BenchmarkXID-4      	50000000	        32.3 ns/op	      32 B/op	       1 allocs/op
BenchmarkUUIDv1     	10000000	       204 ns/op	      48 B/op	       1 allocs/op
BenchmarkUUIDv1-2   	10000000	       160 ns/op	      48 B/op	       1 allocs/op
BenchmarkUUIDv1-4   	10000000	       195 ns/op	      48 B/op	       1 allocs/op
BenchmarkUUIDv4     	 1000000	      1503 ns/op	      64 B/op	       2 allocs/op
BenchmarkUUIDv4-2   	 1000000	      1427 ns/op	      64 B/op	       2 allocs/op
BenchmarkUUIDv4-4   	 1000000	      1452 ns/op	      64 B/op	       2 allocs/op

Note: UUIDv1 requires a global lock, hence the performance degradation as we add more CPUs.

View on Github

7 - Uuid:

Generate, encode, and decode UUIDs v1 with fast or cryptographic-quality random node identifier.

Project Status

v1.1.0 Stable: Guaranteed no breaking changes to the API in future v1.x releases. Probably safe to use in production, though provided on "AS IS" basis.

This package is being actively maintained. If you encounter any problems or have any suggestions for improvement, please open an issue. Pull requests are welcome.

Overview

Package uuid implements generation and manipulation of UUIDs (v1 defined in RFC 4122).

Version 1 UUIDs are time-based and include a node identifier that can be a MAC address or a random 48-bit value.

This package uses the random approach for the node identifier, setting both the 'multicast' and 'local' bits to make sure the value cannot be confused with a real IEEE 802 address (see section 4.5 of RFC 4122). The initial node identifier is a cryptographic-quality random 46-bit value. The first 30 bits can be set and retrieved with the SetNodeId and NodeId functions and method, so that they can be used as a hard-coded instance id. The remaining 16 bits are reserved for increasing the randomness of the UUIDs and to avoid collisions on clock sequence rollovers.

The basic generator New increments the clock sequence on every call and when the counter rolls over the last 16 bits of the node identifier are regenerated using a PRNG seeded at init()-time with the initial node identifier. This approach sacrifices cryptographic quality for speed and for avoiding depletion of the OS entropy pool (yes, it can and does happen).

The NewCrypto generator replaces the clock sequence and last 16 bits of the node identifier on each call with cryptographic-quality random values.

Installation

go get github.com/agext/uuid

View on Github

8 - Uuid:

Implementation of Universally Unique Identifier (UUID). Supports both creation and parsing of UUIDs. Actively maintained fork of satori uuid.

Package uuid provides a pure Go implementation of Universally Unique Identifiers (UUID) variant as defined in RFC-4122. This package supports both the creation and parsing of UUIDs in different formats.

This package supports the following UUID versions:

  • Version 1, based on timestamp and MAC address (RFC-4122)
  • Version 3, based on MD5 hashing of a named value (RFC-4122)
  • Version 4, based on random numbers (RFC-4122)
  • Version 5, based on SHA-1 hashing of a named value (RFC-4122)

This package also supports experimental Universally Unique Identifier implementations based on a draft RFC that updates RFC-4122

  • Version 6, a k-sortable id based on timestamp, and field-compatible with v1 (draft-peabody-dispatch-new-uuid-format, RFC-4122)
  • Version 7, a k-sortable id based on timestamp (draft-peabody-dispatch-new-uuid-format, RFC-4122)

The v6 and v7 IDs are not considered a part of the stable API, and may be subject to behavior or API changes as part of minor releases to this package. They will be updated as the draft RFC changes, and will become stable if and when the draft RFC is accepted.

Project History

This project was originally forked from the github.com/satori/go.uuid repository after it appeared to be no longer maintained, while exhibiting critical flaws. We have decided to take over this project to ensure it receives regular maintenance for the benefit of the larger Go community.

We'd like to thank Maxim Bublis for his hard work on the original iteration of the package.

Installation

It is recommended to use a package manager like dep that understands tagged releases of a package, as well as semantic versioning.

If you are unable to make use of a dependency manager with your project, you can use the go get command to download it directly:

$ go get github.com/gofrs/uuid

Requirements

Due to subtests not being supported in older versions of Go, this package is only regularly tested against Go 1.7+. This package may work perfectly fine with Go 1.2+, but support for these older versions is not actively maintained.

Go 1.11 Modules

As of v3.2.0, this repository no longer adopts Go modules, and v3.2.0 no longer has a go.mod file. As a result, v3.2.0 also drops support for the github.com/gofrs/uuid/v3 import path. Only module-based consumers are impacted. With the v3.2.0 release, all gofrs/uuid consumers should use the github.com/gofrs/uuid import path.

An existing module-based consumer will continue to be able to build using the github.com/gofrs/uuid/v3 import path using any valid consumer go.mod that worked prior to the publishing of v3.2.0, but any module-based consumer should start using the github.com/gofrs/uuid import path when possible and must use the github.com/gofrs/uuid import path prior to upgrading to v3.2.0.

Please refer to Issue #61 and Issue #66 for more details.

Usage

Here is a quick overview of how to use this package. For more detailed documentation, please see the GoDoc Page.

package main

import (
	"log"

	"github.com/gofrs/uuid"
)

// Create a Version 4 UUID, panicking on error.
// Use this form to initialize package-level variables.
var u1 = uuid.Must(uuid.NewV4())

func main() {
	// Create a Version 4 UUID.
	u2, err := uuid.NewV4()
	if err != nil {
		log.Fatalf("failed to generate UUID: %v", err)
	}
	log.Printf("generated Version 4 UUID %v", u2)

	// Parse a UUID from a string.
	s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
	u3, err := uuid.FromString(s)
	if err != nil {
		log.Fatalf("failed to parse UUID %q: %v", s, err)
	}
	log.Printf("successfully parsed UUID %v", u3)
}

View on Github

9 - Uuid:

Go package for UUIDs based on RFC 4122 and DCE 1.1: Authentication and Security Services.

The uuid package generates and inspects UUIDs based on RFC 4122 and DCE 1.1: Authentication and Security Services.

This package is based on the github.com/pborman/uuid package (previously named code.google.com/p/go-uuid). It differs from these earlier packages in that a UUID is a 16 byte array rather than a byte slice. One loss due to this change is the ability to represent an invalid UUID (vs a NIL UUID).

Install

go get github.com/google/uuid

Documentation

Full go doc style documentation for the package can be viewed online without installing this package by using the GoDoc site here: http://pkg.go.dev/github.com/google/uuid

View on Github

10 - Wuid:

An extremely fast unique number generator, 10-135 times faster than UUID.

Overview

  • WUID is a globally unique number generator, while it is NOT a UUID implementation.
  • WUID is 10-135 times faster than UUID and 4600 times faster than generating unique numbers with Redis.
  • Each WUID instance generates unique 64-bit integers in sequence. The high 28 bits are loaded from a data store. By now, Redis, MySQL, MongoDB and Callback are supported.

Benchmarks

BenchmarkWUID       187500764            6.38 ns/op        0 B/op          0 allocs/op
BenchmarkRand       97180698            12.2 ns/op         0 B/op          0 allocs/op
BenchmarkTimestamp  17126514            67.8 ns/op         0 B/op          0 allocs/op
BenchmarkUUID_V1    11986558            99.6 ns/op         0 B/op          0 allocs/op
BenchmarkUUID_V2    12017754           101 ns/op           0 B/op          0 allocs/op
BenchmarkUUID_V3     4925020           242 ns/op         144 B/op          4 allocs/op
BenchmarkUUID_V4    14184271            84.1 ns/op        16 B/op          1 allocs/op
BenchmarkUUID_V5     4277338           274 ns/op         176 B/op          4 allocs/op
BenchmarkRedis         35462         35646 ns/op         176 B/op          5 allocs/op
BenchmarkSnowflake   4931476           244 ns/op           0 B/op          0 allocs/op
BenchmarkULID        8410358           141 ns/op          16 B/op          1 allocs/op
BenchmarkXID        15000969            79.2 ns/op         0 B/op          0 allocs/op
BenchmarkShortID     1738039           698.9 ns/op       311 B/op         11 allocs/op

Features

  • Extremely fast
  • Thread-safe
  • Being unique across time
  • Being unique within a data center
  • Being unique globally if all data centers share a same data store, or they use different section IDs
  • Being capable of generating 100M unique numbers in a single second with each WUID instance
  • Auto-renew when the low 36 bits are about to run out

Install

go get -u github.com/edwingeng/wuid

Usage examples

Redis

import "github.com/edwingeng/wuid/redis/wuid"

newClient := func() (redis.Cmdable, bool, error) {
    var client redis.Cmdable
    // ...
    return client, true, nil
}

// Setup
g := NewWUID("default", nil)
_ = g.LoadH28FromRedis(newClient, "wuid")

// Generate
for i := 0; i < 10; i++ {
    fmt.Printf("%#016x\n", g.Next())
}

MySQL

import "github.com/edwingeng/wuid/mysql/wuid"

newDB := func() (*sql.DB, bool, error) {
    var db *sql.DB
    // ...
    return db, true, nil
}

// Setup
g := NewWUID("default", nil)
_ = g.LoadH28FromMysql(newDB, "wuid")

// Generate
for i := 0; i < 10; i++ {
    fmt.Printf("%#016x\n", g.Next())
}

View on Github

Thank you for following this article.

Related videos:

Universally Unique Identifiers (UUID/GUID) // Game Engine series

#go #golang #uuid 

Fannie  Zemlak

Fannie Zemlak

1599854400

What's new in the go 1.15

Go announced Go 1.15 version on 11 Aug 2020. Highlighted updates and features include Substantial improvements to the Go linker, Improved allocation for small objects at high core counts, X.509 CommonName deprecation, GOPROXY supports skipping proxies that return errors, New embedded tzdata package, Several Core Library improvements and more.

As Go promise for maintaining backward compatibility. After upgrading to the latest Go 1.15 version, almost all existing Golang applications or programs continue to compile and run as older Golang version.

#go #golang #go 1.15 #go features #go improvement #go package #go new features

Top 8 Machine Learning Libraries In Go Language One Must Know

Created by Google researchers, Go is a popular open-source programming language. The language includes many intuitive features, including a garbage collector, cross-platform, efficient concurrency, among others.

According to the Stack Overflow Developer Survey 2020, Go language is not only the fifth most loved programming language but also fetches the programmers the third-highest salary among other languages.

Below here, we list down the top machine learning libraries in Go language.

#opinions #go language #google ml tools #machine learning libraries #ml libraries #ml libraries in go

Alice Cook

Alice Cook

1614329473

Fix: G Suite not Working | G Suite Email not Working | Google Business

G Suite is one of the Google products, developed form of Google Apps. It is a single platform to hold cloud computing, collaboration tools, productivity, software, and products. While using it, many a time, it’s not working, and users have a question– How to fix G Suite not working on iPhone? It can be resolved easily by restarting the device, and if unable to do so, you can reach our specialists whenever you want.
For more details: https://contactforhelp.com/blog/how-to-fix-the-g-suite-email-not-working-issue/

#g suite email not working #g suite email not working on iphone #g suite email not working on android #suite email not working on windows 10 #g suite email not working on mac #g suite email not syncing

Nigel  Uys

Nigel Uys

1663248360

10 Best Libraries for Working with Forms in Go

In today's post we will learn about 10 Best Libraries for Working with Forms in Go. 

What is Working with Forms?

Forms are used to receive information from the user. Forms are commonly used to allow users to register on a Web site, to log in to a Web site, to order a product, and to send feedback. In search engines, forms are used to accept the keywords for search.

The <form> tag is used to create a form. An HTML from starts with <form> and ends with </form> tag. Forms contain many types of form elements, such as text boxes, radio buttons, check boxes, buttons and drop-down lists.

The form has a special element, which is submit button, which will submit the entries of a form to a server application to process the entries. Each element in the form is assigned a name using the name attribute. Users enter values into the text boxes, or make selections from the radio buttons, check boxes, and drop down lists. The values they enter or select are passed with the name of the corresponding form element to the Web server.

Table of contents:

  • Bind - Bind form data to any Go values.
  • Binding - Binds form and JSON data from net/http Request to struct.
  • Conform - Keeps user input in check. Trims, sanitizes & scrubs data based on struct tags.
  • Form - Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.
  • Formam - decode form's values into a struct.
  • Forms - Framework-agnostic library for parsing and validating form/JSON data which supports multipart forms and files.
  • Gbind - Bind data to any Go value. Can use built-in and custom expression binding capabilities; supports data validation
  • Gorilla/csrf - CSRF protection for Go web applications & services.
  • Httpin - Decode an HTTP request into a custom struct, including querystring, forms, HTTP headers, etc.
  • Nosurf - CSRF protection middleware for Go.

1 - Bind: Bind form data to any Go values.

Bind is a library for binding HTTP request parameters to Go objects.

It comes with binders for all values, time.Time, arbitrary structs, and slices. In particular, binding functions are provided for the following types:

  • bool
  • float32, float64
  • int, int8, int16, int32, int64
  • uint, uint8, uint16, uint32, uint64
  • string
  • struct
  • a pointer to any supported type
  • a slice of any supported type
  • time.Time
  • uploaded files (as io.Reader, io.ReadSeeker, *os.File, []byte, *multipart.FileHeader)

Callers may also hook into the process and provide a custom binding function.

Example

This example binds data from embedded URL arguments, the query string, and a posted form.

POST /accounts/:accountId/users/?op=UPDATE

<form>
 <input name="user.Id">
 <input name="user.Name">
 <input name="user.Phones[0].Label">
 <input name="user.Phones[0].Number">
 <input name="user.Phones[1].Label">
 <input name="user.Phones[1].Number">
 <input name="user.Labels[]">
 <input name="user.Labels[]">
</form>

type Phone struct { Label, Number string }
type User struct {
  Id     uint32
  Phones []Phone
  Labels []string
}

var (
  params = mux.Vars(req) // embedded URL args
  id     uint32
  op     string
  user   User
)
handleErrors(
  bind.Map(params).Field(&id, "accountId"),
  bind.Request(req).Field(&op, "op")
  bind.Request(req).Field(&user, "user"),
)

Booleans

Booleans are converted to Go by comparing against the following strings:

TRUE: "true", "1",  "on"
FALSE: "false", "0", ""

The "on" / "" syntax is supported as the default behavior for HTML checkboxes.

View on Github

2 - Binding: Binds form and JSON data from net/http Request to struct.

Reflectionless data binding for Go's net/http

Features

  • HTTP request data binding
  • Data validation (custom and built-in)
  • Error handling

Benefits

  • Moves data binding, validation, and error handling out of your application's handler
  • Reads Content-Type to deserialize form, multipart form, and JSON data from requests
  • No middleware: just a function call
  • Usable in any setting where net/http is present (Negroni, gocraft/web, std lib, etc.)
  • No reflection

Usage example

package main

import (
	"fmt"
	"net/http"

	"github.com/mholt/binding"
)

// First define a type to hold the data
// (If the data comes from JSON, see: http://mholt.github.io/json-to-go)
type ContactForm struct {
	User struct {
		ID int
	}
	Email   string
	Message string
}

// Then provide a field mapping (pointer receiver is vital)
func (cf *ContactForm) FieldMap(req *http.Request) binding.FieldMap {
	return binding.FieldMap{
		&cf.User.ID: "user_id",
		&cf.Email:   "email",
		&cf.Message: binding.Field{
			Form:     "message",
			Required: true,
		},
	}
}

// Now your handlers can stay clean and simple
func handler(resp http.ResponseWriter, req *http.Request) {
	contactForm := new(ContactForm)
	if errs := binding.Bind(req, contactForm); errs != nil {
		http.Error(resp, errs.Error(), http.StatusBadRequest)
		return
	}
	fmt.Fprintf(resp, "From:    %d\n", contactForm.User.ID)
	fmt.Fprintf(resp, "Message: %s\n", contactForm.Message)
}

func main() {
	http.HandleFunc("/contact", handler)
	http.ListenAndServe(":3000", nil)
}

View on Github

3 - Conform: Keeps user input in check. Trims, sanitizes & scrubs data based on struct tags.

Conform- keep user input in check (go, golang)

Trim, sanitize, and modify struct string fields in place, based on tags.

Now also works with embedded structs

Turns this...

type Person struct {
	FirstName string `conform:"name"`
	LastName  string `conform:"ucfirst,trim"`
	Email     string `conform:"email"`
	CamelCase string `conform:"camel"`
	UserName  string `conform:"snake"`
	Slug      string `conform:"slug"`
	Blurb     string `conform:"title"`
	Left      string `conform:"ltrim"`
	Right     string `conform:"rtrim"`
}

p1 := Person{
	" LEE ",
	"     Benson",
	"   LEE@LEEbenson.com  ",
	"I love new york city",
	"lee benson",
	"LeeBensonWasHere",
	"this is a little bit about me...",
	"    Left trim   ",
	"    Right trim  ",
}

Into this...

p2 := p1 // <-- copy the Person struct into a new one, to see the difference
conform.Strings(&p2) // <-- this does the work

/*
	p1 (left) vs. p2 (right)

	FirstName: ' LEE ' -> 'Lee'
	LastName: '     Benson' -> 'Benson'
	Email: '   LEE@LEEbenson.com  ' -> 'lee@leebenson.com'
	CamelCase: 'I love new york city' -> 'ILoveNewYorkCity'
	UserName: 'lee benson' -> 'lee_benson'
	Slug: 'LeeBensonWasHere' -> 'lee-benson-was-here'
	Blurb: 'this is a little bit about me...' -> 'This Is A Little Bit About Me...'
	Left: '    Left trim   ' -> 'Left trim   '
	Right: '    Right trim  ' -> '    Right trim'
*/

View on Github

4 - Form: Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support.

Package form Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values.

Installation

Use go get.

go get github.com/go-playground/form

Then import the form package into your own code.

import "github.com/go-playground/form/v4"

Usage

  • Use symbol . for separating fields/structs. (eg. structfield.field)
  • Use [index or key] for access to index of a slice/array or key for map. (eg. arrayfield[0], mapfield[keyvalue])
<form method="POST">
  <input type="text" name="Name" value="joeybloggs"/>
  <input type="text" name="Age" value="3"/>
  <input type="text" name="Gender" value="Male"/>
  <input type="text" name="Address[0].Name" value="26 Here Blvd."/>
  <input type="text" name="Address[0].Phone" value="9(999)999-9999"/>
  <input type="text" name="Address[1].Name" value="26 There Blvd."/>
  <input type="text" name="Address[1].Phone" value="1(111)111-1111"/>
  <input type="text" name="active" value="true"/>
  <input type="text" name="MapExample[key]" value="value"/>
  <input type="text" name="NestedMap[key][key]" value="value"/>
  <input type="text" name="NestedArray[0][0]" value="value"/>
  <input type="submit"/>
</form>

Examples

Decoding

package main

import (
	"fmt"
	"log"
	"net/url"

	"github.com/go-playground/form/v4"
)

// Address contains address information
type Address struct {
	Name  string
	Phone string
}

// User contains user information
type User struct {
	Name        string
	Age         uint8
	Gender      string
	Address     []Address
	Active      bool `form:"active"`
	MapExample  map[string]string
	NestedMap   map[string]map[string]string
	NestedArray [][]string
}

// use a single instance of Decoder, it caches struct info
var decoder *form.Decoder

func main() {
	decoder = form.NewDecoder()

	// this simulates the results of http.Request's ParseForm() function
	values := parseForm()

	var user User

	// must pass a pointer
	err := decoder.Decode(&user, values)
	if err != nil {
		log.Panic(err)
	}

	fmt.Printf("%#v\n", user)
}

// this simulates the results of http.Request's ParseForm() function
func parseForm() url.Values {
	return url.Values{
		"Name":                []string{"joeybloggs"},
		"Age":                 []string{"3"},
		"Gender":              []string{"Male"},
		"Address[0].Name":     []string{"26 Here Blvd."},
		"Address[0].Phone":    []string{"9(999)999-9999"},
		"Address[1].Name":     []string{"26 There Blvd."},
		"Address[1].Phone":    []string{"1(111)111-1111"},
		"active":              []string{"true"},
		"MapExample[key]":     []string{"value"},
		"NestedMap[key][key]": []string{"value"},
		"NestedArray[0][0]":   []string{"value"},
	}
}

View on Github

5 - Formam: Decode form's values into a struct.

A Go package to decode HTTP form and query parameters. The only requirement is Go 1.12 or later.

Install

go get github.com/monoculum/formam/v3

Features

  • Infinite nesting for maps, structs and slices.
  • Support UnmarshalText() interface in values and keys of maps.
  • Supported map keys are string, int and variants, uint and variants, uintptr, float32, float64, bool, struct, custom types to one of the above types registered by function or UnmarshalText method, a pointer to one of the above types
  • A field with interface{} that has a map, struct or slice as value is accessible.
  • Decode time.Time with format 2006-01-02 by its UnmarshalText() method.
  • Decode url.URL.
  • Append to slice and array types without explicitly indicating an index.
  • Register a function for a custom type.

Performance

You can see the performance in formam-benchmark compared with ajg/form, gorilla/schema, go-playground/form and built-in/json.

Basic usage example

In form HTML

  • Use . to access a struct field (e.g. struct.field1).
  • Use [<index>] to access tje specific slice/array index (e.g. struct.array[0]). It's not necessary to add an index to append data.
  • Use [<key>] to access map keys (e.g.. struct.map[es-ES]).
<form method="POST">
  <input type="text" name="Name" value="Sony" />
  <input type="text" name="Location.Country" value="Japan" />
  <input type="text" name="Location.City" value="Tokyo" />
  <input type="text" name="Products[0].Name" value="Playstation 4" />
  <input type="text" name="Products[0].Type" value="Video games" />
  <input type="text" name="Products[1].Name" value="TV Bravia 32" />
  <input type="text" name="Products[1].Type" value="TVs" />
  <input type="text" name="Founders[0]" value="Masaru Ibuka" />
  <input type="text" name="Founders[0]" value="Akio Morita" />
  <input type="text" name="Employees" value="90000" />
  <input type="text" name="public" value="true" />
  <input type="url" name="website" value="http://www.sony.net" />
  <input type="date" name="foundation" value="1946-05-07" />
  <input type="text" name="Interface.ID" value="12" />
  <input type="text" name="Interface.Name" value="Go Programming Language" />
  <input type="submit" />
</form>

View on Github

6 - Forms: Framework-agnostic library for parsing and validating form/JSON data which supports multipart forms and files.

Forms is a lightweight, but incredibly useful go library for parsing form data from an http.Request. It supports multipart forms, url-encoded forms, json data, and url query parameters. It also provides helper methods for converting data into other types and a Validator object which can be used to validate the data. Forms is framework-agnostic and works directly with the http package.

Version 0.4.0

Development Status

Forms is being actively developed and is well-tested. However, since it is still a young library, it is not recommended for use in mission-critical production applications at this time. It is probably fine to use for low-traffic hobby sites, and in fact we encourage its use in those settings to help polish the API and find missing features and hidden bugs. Pull requests and issue reports are much appreciated :)

Forms follows semantic versioning but offers no guarantees of backwards compatibility until version 1.0. Keep in mind that breaking changes might occur. We will do our best to make the community aware of any non-trivial breaking changes beforehand. We recommend using a dependency vendoring tool such as godep to ensure that breaking changes will not break your application.

Installation

Install like you would any other package:

go get github.com/albrow/forms

Then include the package in your import statements:

import "github.com/albrow/forms"

Example Usage

Meant to be used inside the body of an http.HandlerFunc or any function that has access to an http.Request.

func CreateUserHandler(res http.ResponseWriter, req *http.Request) {
	// Parse request data.
	userData, err := forms.Parse(req)
	if err != nil {
		// Handle err
		// ...
	}

	// Validate
	val := userData.Validator()
	val.Require("username")
	val.LengthRange("username", 4, 16)
	val.Require("email")
	val.MatchEmail("email")
	val.Require("password")
	val.MinLength("password", 8)
	val.Require("confirmPassword")
	val.Equal("password", "confirmPassword")
	val.RequireFile("profileImage")
	val.AcceptFileExts("profileImage", "jpg", "png", "gif")
	if val.HasErrors() {
		// Write the errors to the response
		// Maybe this means formatting the errors as json
		// or re-rendering the form with an error message
		// ...
	}

	// Use data to create a user object
	user := &models.User {
		Username: userData.Get("username"),
		Email: userData.Get("email"),
		HashedPassword: hash(userData.Get("password")),
	}

	// Continue by saving the user to the database and writing
	// to the response
	// ...


	// Get the contents of the profileImage file
	imageBytes, err := userData.GetFileBytes("profileImage")
	if err != nil {
	  // Handle err
	}
	// Now you can either copy the file over to your server using io.Copy,
	// upload the file to something like amazon S3, or do whatever you want
	// with it.
}

View on Github

7 - Gbind: Bind data to any Go value. Can use built-in and custom expression binding capabilities; supports data validation.

gbind

Encapsulate general parameter parsing and parameter verification logic, 
minimize repetitive code in daily development, and solve parameter binding 
and verification in a few lines of code

Features

  • Bind data to the specified structure based on tag information
    • Built-in HTTP request path, query, form, header, cookie binding ability
      • Binding for http uri parameters gbind:"http.path"
      • Binding for http query parameters gbind:"http.query.varname"
      • Binding for http header parameters gbind:"http.header.varname"
      • Binding for http form parameters gbind:"http.form.varname"
      • Binding for http cookie parameters gbind:"http.cookie.varname"
    • Built-in json binding capability, implemented with encoding/json
      • For HTTP body in json format, follow golang json parsing format uniformly json:"varname"
    • Support for setting default values of bound fields
      • Supports setting default values of bound fields when no data is passed in gbind:"http.query.varname,default=123"
    • Support custom binding parsing logic (not limited to HTTP requests, using gbind can do bindings similar to database tags and other scenarios)
      • You can register custom binding logic by calling the RegisterBindFunc function, such as implementing a binding of the form gbind:"simple.key"
  • Validate the field value according to the tag information, parameter validation logic refer to the validate package
    • Data validation of bound fields is performed according to the defined validatetag, which depends on github.com/go-playground/validator implementation, validate="required,lt=100"
    • Support custom validation logic, you can customize the data validation logic by calling the RegisterCustomValidation function
    • Support custom error message for validation failure
    • By defining the tag of err_msg, it supports custom error message when parameter validation fails, demo gbind:"http.cookie.Token" validate="required,lt=100" err_msg="Please complete the login"

Usage example

  • Use gbind's web API request parameters for binding and verification
package gbind

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"net/url"
)

type Params struct {
	API    string `gbind:"http.path,default=/api/test"`
	Appkey string `gbind:"http.query.appkey,default=appkey-default"`
	Page   int    `gbind:"http.query.page,default=1"`
	Size   int    `gbind:"http.query.size,default=10"`
	Token  string `gbind:"http.cookie.Token" validate:"required" err_msg:"please login"`
	Host   string `gbind:"http.header.host,default=www.baidu.com"`
	Uids   []int  `gbind:"http.form.uids"`
}

func Controller(w http.ResponseWriter, r *http.Request) {
	var requestParams = &Params{}
	if _, err := BindWithValidate(context.Background(), requestParams, r); err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	bs, _ := json.MarshalIndent(requestParams, "", "\t")
	w.Write(bs)
}

func ExampleGbind() {
	w := httptest.NewRecorder()
	u, _ := url.Parse("http://gbind.baidu.com/api/test?appkey=abc&page=2")
	r := &http.Request{
		Method: http.MethodPost,
		Header: map[string][]string{
			"Host": {"gbind.baidu.com"},
		},
		PostForm: url.Values{
			"uids": {"1", "2", "3"},
		},
		URL: u,
	}
	r.AddCookie(&http.Cookie{
		Name:  "Token",
		Value: "foo-bar-andsoon",
	})

	Controller(w, r)

	fmt.Println(w.Result().Status)
	fmt.Println(w.Body.String())

	// Output:
	// 200 OK
	//{
	//	"API": "/api/test",
	//	"Appkey": "abc",
	//	"Page": 2,
	//	"Size": 10,
	//	"Token": "foo-bar-andsoon",
	//	"Host": "gbind.baidu.com",
	//	"Uids": [
	//		1,
	//		2,
	//		3
	//	]
	//}
}

View on Github

8 - Gorilla/csrf: CSRF protection for Go web applications & services.

gorilla/csrf is a HTTP middleware library that provides cross-site request forgery (CSRF) protection. It includes:

  • The csrf.Protect middleware/handler provides CSRF protection on routes attached to a router or a sub-router.
  • A csrf.Token function that provides the token to pass into your response, whether that be a HTML form or a JSON response body.
  • ... and a csrf.TemplateField helper that you can pass into your html/template templates to replace a {{ .csrfField }} template tag with a hidden input field.

gorilla/csrf is designed to work with any Go web framework, including:

gorilla/csrf is also compatible with middleware 'helper' libraries like Alice and Negroni.

Install

With a properly configured Go toolchain:

go get github.com/gorilla/csrf

Examples

gorilla/csrf is easy to use: add the middleware to your router with the below:

CSRF := csrf.Protect([]byte("32-byte-long-auth-key"))
http.ListenAndServe(":8000", CSRF(r))

...and then collect the token with csrf.Token(r) in your handlers before passing it to the template, JSON body or HTTP header (see below).

Note that the authentication key passed to csrf.Protect([]byte(key)) should:

  • be 32-bytes long
  • persist across application restarts.
  • kept secret from potential malicious users - do not hardcode it into the source code, especially not in open-source applications.

Generating a random key won't allow you to authenticate existing cookies and will break your CSRF validation.

gorilla/csrf inspects the HTTP headers (first) and form body (second) on subsequent POST/PUT/PATCH/DELETE/etc. requests for the token.

HTML Forms

Here's the common use-case: HTML forms you want to provide CSRF protection for, in order to protect malicious POST requests being made:

package main

import (
    "net/http"

    "github.com/gorilla/csrf"
    "github.com/gorilla/mux"
)

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/signup", ShowSignupForm)
    // All POST requests without a valid token will return HTTP 403 Forbidden.
    // We should also ensure that our mutating (non-idempotent) handler only
    // matches on POST requests. We can check that here, at the router level, or
    // within the handler itself via r.Method.
    r.HandleFunc("/signup/post", SubmitSignupForm).Methods("POST")

    // Add the middleware to your router by wrapping it.
    http.ListenAndServe(":8000",
        csrf.Protect([]byte("32-byte-long-auth-key"))(r))
    // PS: Don't forget to pass csrf.Secure(false) if you're developing locally
    // over plain HTTP (just don't leave it on in production).
}

func ShowSignupForm(w http.ResponseWriter, r *http.Request) {
    // signup_form.tmpl just needs a {{ .csrfField }} template tag for
    // csrf.TemplateField to inject the CSRF token into. Easy!
    t.ExecuteTemplate(w, "signup_form.tmpl", map[string]interface{}{
        csrf.TemplateTag: csrf.TemplateField(r),
    })
    // We could also retrieve the token directly from csrf.Token(r) and
    // set it in the request header - w.Header.Set("X-CSRF-Token", token)
    // This is useful if you're sending JSON to clients or a front-end JavaScript
    // framework.
}

func SubmitSignupForm(w http.ResponseWriter, r *http.Request) {
    // We can trust that requests making it this far have satisfied
    // our CSRF protection requirements.
}

Note that the CSRF middleware will (by necessity) consume the request body if the token is passed via POST form values. If you need to consume this in your handler, insert your own middleware earlier in the chain to capture the request body.

View on Github

9 - Httpin: Decode an HTTP request into a custom struct, including querystring, forms, HTTP headers, etc.

Core Features

httpin helps you easily decoding HTTP request data from

  • Query parameters, e.g. ?name=john&is_member=true
  • Headers, e.g. Authorization: xxx
  • Form data, e.g. username=john&password=******
  • JSON/XML Body, e.g. POST {"name":"john"}
  • Path variables, e.g. /users/{username}
  • File uploads

You only need to define a struct to receive/bind data from an HTTP request, without writing any parsing stuff code by yourself.

How to use?

type ListUsersInput struct {
	Page     int  `in:"query=page"`
	PerPage  int  `in:"query=per_page"`
	IsMember bool `in:"query=is_member"`
}

func ListUsers(rw http.ResponseWriter, r *http.Request) {
	input := r.Context().Value(httpin.Input).(*ListUsersInput)

	if input.IsMember {
		// Do sth.
	}
	// Do sth.
}

httpin is:

Why this package?

Compared with using net/http package

func ListUsers(rw http.ResponseWriter, r *http.Request) {
	page, err := strconv.ParseInt(r.FormValue("page"), 10, 64)
	if err != nil {
		// Invalid parameter: page.
		return
	}
	perPage, err := strconv.ParseInt(r.FormValue("per_page"), 10, 64)
	if err != nil {
		// Invalid parameter: per_page.
		return
	}
	isMember, err := strconv.ParseBool(r.FormValue("is_member"))
	if err != nil {
		// Invalid parameter: is_member.
		return
	}

	// Do sth.
}

View on Github

10 - Nosurf: CSRF protection middleware for Go.

nosurf is an HTTP package for Go that helps you prevent Cross-Site Request Forgery attacks. It acts like a middleware and therefore is compatible with basically any Go HTTP application.

Why?

Even though CSRF is a prominent vulnerability, Go's web-related package infrastructure mostly consists of micro-frameworks that neither do implement CSRF checks, nor should they.

nosurf solves this problem by providing a CSRFHandler that wraps your http.Handler and checks for CSRF attacks on every non-safe (non-GET/HEAD/OPTIONS/TRACE) method.

nosurf requires Go 1.1 or later.

Features

  • Supports any http.Handler (frameworks, your own handlers, etc.) and acts like one itself.
  • Allows exempting specific endpoints from CSRF checks by an exact URL, a glob, or a regular expression.
  • Allows specifying your own failure handler. Want to present the hacker with an ASCII middle finger instead of the plain old HTTP 400? No problem.
  • Uses masked tokens to mitigate the BREACH attack.
  • Has no dependencies outside the Go standard library.

Example

package main

import (
	"fmt"
	"github.com/justinas/nosurf"
	"html/template"
	"net/http"
)

var templateString string = `
<!doctype html>
<html>
<body>
{{ if .name }}
<p>Your name: {{ .name }}</p>
{{ end }}
<form action="/" method="POST">
<input type="text" name="name">

<!-- Try removing this or changing its value
     and see what happens -->
<input type="hidden" name="csrf_token" value="{{ .token }}">
<input type="submit" value="Send">
</form>
</body>
</html>
`
var templ = template.Must(template.New("t1").Parse(templateString))

func myFunc(w http.ResponseWriter, r *http.Request) {
	context := make(map[string]string)
	context["token"] = nosurf.Token(r)
	if r.Method == "POST" {
		context["name"] = r.FormValue("name")
	}
	
	templ.Execute(w, context)
}

func main() {
	myHandler := http.HandlerFunc(myFunc)
	fmt.Println("Listening on http://127.0.0.1:8000/")
	http.ListenAndServe(":8000", nosurf.New(myHandler))
}

View on Github

Thank you for following this article.

#go #golang #working #forms