gofrs / uuid Goto Github PK
View Code? Open in Web Editor NEWA UUID package for Go
License: MIT License
A UUID package for Go
License: MIT License
When 1.11 is released, we should add support for it to travis, as described in #44 (comment).
I am currently working on this and will PR it in later.
Main change is testing with go 1.10 and checking for any issues with operation.
I see NullUUID
has an UnmarshalJSON
capability, is there any reason one hasn't been implemented for UUID
? I imagine this should have the same implementation as UnmarshallText
Super keen to use this package for an API but struggling to unmarshal POST JSON content
While overall there's nothing wrong with the go-check
package, as least from my perspective as a user, it does add some overhead in to learning how to contribute unit tests to this package. We should look at replacing the go-check assertions with table-driven tests using the testing
package from the stdlib.
(This is already a WIP)
Hi! First of all, thanks for the library!
AFAIK the new UUID drafts didn't change the uuidv6 / uuidv7 implementations, the README could be updated to say that this library is compatible with the most recent draft. WDYT?
Link to the new draft: https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-02
Edit: actually it looks like there are some changes to the uuidv6 implementation since the referenced draft in the readme.
Don't know if you was aware of this fork that i just discover:
https://github.com/gobuffalo/uuid
I should use this package or the original one (https://github.com/satori/go.uuid)?
it's not clear in docs.
Since this package touches untrusted user input, it would be a good idea to fuzz FromString
, (*UUID).UnmarshalText
and similar.
Assuming we use https://github.com/dvyukov/go-fuzz, what should we do about the fuzz testing corpus? I think there are three options:
testdata/{corpus,crashers,suppressions}
: this clutters things quite a bit, unfortunatelygofrs/uuid-test-corpus
: this may be overkillThoughts?
Apologies if I am missing something, but it appears the current implementation of TimestampFromV7()
uses the Gregorian epoch timestamp as opposed to unix:
Line 156 in 22c52c2
Lines 37 to 39 in 22c52c2
The draft states:
unix_ts_ms:
48 bit big-endian unsigned number of Unix epoch timestamp as per Section 6.1.
So shouldn't this be:
func TimestampFromV7(u UUID) (Timestamp, error) {
if u.Version() != 7 {
return 0, fmt.Errorf("uuid: %s is version %d, not version 6", u, u.Version())
}
t := 0 |
(int64(u[0]) << 40) |
(int64(u[1]) << 32) |
(int64(u[2]) << 24) |
(int64(u[3]) << 16) |
(int64(u[4]) << 8) |
int64(u[5])
return Timestamp(t), nil
}
Where tests would be as straightforward as:
tests := []struct {
u UUID
want Timestamp
wanterr bool
}{
{u: Must(FromString("00000000-0000-7000-0000-000000000000")), want: Timestamp(0x000000000000)},
{u: Must(FromString("018a8fec-3ced-7164-995f-93c80cbdc575")), want: Timestamp(0x018a8fec3ced)},
{u: Must(FromString("ffffffff-ffff-7fff-ffff-ffffffffffff")), want: Timestamp(0xffffffffffff)},
}
Right now to tell if a UUID is entirely empty, you need to do this fairly clunky operation:
if bytes.Equal(myUUID[:], uuid.Nil[:]) {
...
}
It might be nice to add IsZero()
- matching the API for time.Time
- that will handle this for you.
This bug tracks development towards a v1.3.0 release and a more formal announcement of the library.
Those things aside, do we want to do anything else for v1.3.0?
We should take a look at the open issues and pending PRs in https://github.com/satori/go.uuid and see if which ones would be worth tackling / adopting.
satori/go.uuid#44 was brought up, which I think is a good start.
Please comment with other issues or PRs if you think they'd be worth doing.
When parsing a time.Time
value from a v1 uuid using UUID.TimestampFromV1
, the Timestamp.Time
function is called. This function only ever returns a nil
error. Why does this function have an error for the second return argument when one can't ever be produced?
Lines 72 to 85 in 094e8c2
Hi
I was wondering if you had any interest in support for go1.13 error wrapping? For example:
const (
ErrIncorrectLength Error = iota + 1
// Other sentinel error types here
)
type Error int
func (e Error) Error() string {
switch e {
case ErrIncorrectLength:
return "incorrect length"
// Other error strings here
default:
return "unknown error"
}
}
func (u *UUID) UnmarshalText(text []byte) error {
switch len(text) {
// Previous switch conditions
default:
return fmt.Errorf("uuid: %w %d in string %q", ErrIncorrectLength, len(text), text)
}
}
This would allow for the usage of errors.Is()
and errors.As()
, useful for testing or performing other conditional logic based on the type of error, for example:
id, err := uuid.FromString("foo")
if err != nil {
if errors.Is(err, uuid.ErrIncorrectLength) {
// some bespoke logic
}
}
If you approve I'd be more than happy to open a PR with the implementation detail.If backwards compatibility is a concern we can probably get around it with build tags.
Demo over on the playground: https://play.golang.org/p/H5teBSdvfct
Hi,
I have a need to encode a specific timestamp (instead of time.Now()) into a V1 UUID. There doesn't seem to be a way to do that. Before I start coding the change for that, I'm checking to see if this is something that is generally useful or if I should just maintain my own code to do this.
Thoughts?
Our coveralls integration hasn't been so consistent when it comes to detecting regressions in code coverage, to the point of being annoying and erroneously failing builds. Let's see whether Codecov can act as a replacement, and if not decide whether we should just rip coveralls out or determine alternate options.
Once we get Travis and similar things set up, we should make them point to this repository.
the opposite of the nil, its useful constant to have around.
i'll also note both should be better served by functions as global vars are mutable.
We added a go.mod
in #44, but we did not cut a release after that, which means that the go.mod
file is not working as expected, unfortunately. Importing github.com/gofrs/uuid/v3
fails with a pretty cryptic error right now.
We should cut v3.1.1, to make modules work correctly.
Could you please do the honors, @theckman?
EDIT: it was explained to me that the reason it doesn't work is
because the new tag is still a question to be answered: should it be
v3.1.1
orv3.2.0
orv4.0.0
which makes some sense, I suppose.
I think it would be helpful if we contacted https://awesome-go.com/ and explained the situation
This fork should be added with no doubts, but it's not certain to me whether the original one should be marked explicitly somehow.
I've found myself encoding the UUID to Base64 and Base32 string in multiple projects I worked on.
Do you think it's a good idea if we add this encoding and decoding to this library or that's out of its scope?
Thanks
After converting my own project into go.mod and run go test all
under module root, got:
--- FAIL: TestGenerator (0.02s)
--- FAIL: TestGenerator/NewV2 (0.00s)
--- FAIL: TestGenerator/NewV2/DifferentAcrossCalls (0.00s)
generator_test.go:210: generated identical UUIDs across calls: 3912a521-2f04-21e9-8002-309c238cfc62
FAIL
FAIL github.com/gofrs/uuid 0.757s
Is this function just missing or is there a reason why its not added?
This matter came to light with the submission of #17. In reworking the tests, I unfortunately omitted the fact that Go < 1.7 doesn't have subtests, so the Travis builds for < 1.7 are failing.
In the context of that PR, I think the relevant questions are whether or not testing for Go >= 1.3 && Go < 1.7 adds value for users who are stuck on those versions, and whether they'd be comfortable using the package if regular tests only run on Go >= 1.7.
If we assume that the package will have users in that category, and we believe the answer to the former question to be "yes" (and the answer to the latter to be "no"), then I can refactor the tests to work on < 1.7.
On the other hand, subtests are a nice modernization, and they fit the nature of the tests quite well.
If the subtests stay, the documentation w.r.t. supported versions could read "tested on >= 1.7, probably works on >= 1.2". If we remove subtests, the documentation will continue to say "tested on >= 1.3, probably works on >= 1.2".
Thoughts?
Hello.
So, it's likely proposal and discussion start. Don't you mind to add a generator's constructor that allows to specify custom rand data source? Something like this:
func NewGenWithRand(r io.Reader) *Gen {
return &Gen{
epochFunc: time.Now,
hwAddrFunc: defaultHWAddrFunc,
rand: r,
}
}
For code like
func (u *UUID) decodeHashLike(t []byte) (err error) {
src := t[:]
dst := u[:]
if _, err = hex.Decode(dst, src); err != nil {
return err
}
return
}
or
func (u UUID) MarshalBinary() (data []byte, err error) {
data = u.Bytes()
return
}
named return values to me don't add any value but mental overhead.
I suggest to vote whether we keep it as-is (then the "rule" should be standardised - so that it was applied consistently, now not all functions have it) or remove, unless it really is one of those rare cases when it makes something "more readable" (and yes, I understand it's subjective).
🎉 - to keep and standardise
❤️ - to remove
Seems like the UUID library returns the wrong error message for function TimestampFromV7
.
The returned error message is (with input 'e86160d3-beff-443c-b9b5-1f8197ccb12e':
uuid: e86160d3-beff-443c-b9b5-1f8197ccb12e is version 4, not version 6
The expected error message should be:
uuid: e86160d3-beff-443c-b9b5-1f8197ccb12e is version 4, not version 7
The new %S
verb seems to cause go vet
in Go 1.12.x
to fail when vetting code that tries to use it, as it believes %S
is not a supported verb. This does not fail for 1.11.x
or tip
. A Go issue was opened to track this: golang/go#31000.
This is blocking the release of v3.3.0
, and v4.0.0
(#71).
$ go vet file.go
# command-line-arguments
./bleh.go:14:2: Printf format %S has unknown verb S
package main
import (
"log"
"github.com/gofrs/uuid"
)
func main() {
u2, err := uuid.NewV4()
if err != nil {
log.Fatalf("failed to generate UUID: %v", err)
}
log.Printf("capitalized UUID: %S\n", u2) /* ERROR HERE !! */
}
// Example output:
// 2019/03/22 01:17:20 capitalized UUID: 8BB2BE92-2573-435A-8A4C-CAD633636165
https://github.com/gofrs/uuid/blob/22c52c268bc0dcc0569793f5b1433db423f5a9c6/uuid.go#L286C1-L286C36
according to https://go.dev/tour/methods/8
In general, all methods on a given type should have either value or pointer receivers, but not a mixture of both. (We'll see why over the next few pages.)
With the introduction of the go.mod
file and declaration of github.com/gofrs/uuid/v3
there is no longer a single import path that works correctly for both modules and non-modules users.
This has become an issue with gobuffalo/pop and other Buffalo projects.
Below you find a selection of go get
statements that represent the different import paths and what happens when trying to use them in different environments.
GO111MODULE=off
)$ go get github.com/gofrs/uuid/v3
package github.com/gofrs/uuid/v3: cannot find package "github.com/gofrs/uuid/v3" in any of:
/usr/local/go/src/github.com/gofrs/uuid/v3 (from $GOROOT)
/go/src/github.com/gofrs/uuid/v3 (from $GOPATH)
GO111MODULE=on
)$ go get github.com/gofrs/uuid
module github.com/gobuffalo/uuidmods
require github.com/gofrs/uuid v3.1.0+incompatible // indirect
$ go get github.com/gofrs/uuid/v3
module github.com/gobuffalo/uuidmods
require (
github.com/gofrs/uuid/v3 v3.1.2 // indirect
)
The current package does not allow me to supply my own io.Reader
to use in place of the default rand.Reader
. The use case for this is reproducible tests where I can guarantee the same output by providing a rand
with a specific seed. Instead, I have to verify in tests that the output of my function is a string in the form of a UUID.
FromString("{6ba7b810-9dad-11d1-80b4-00c04fd430c8}")
works fine, but FromString("{6ba7b8109dad11d180b400c04fd430c8}")
returns an error.
The documentation for UnmarshalText
says:
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
// "6ba7b8109dad11d180b400c04fd430c8"
// ABNF for supported UUID text representation follows:
// uuid := canonical | hashlike | braced | urn
// plain := canonical | hashlike
// canonical := 4hexoct '-' 2hexoct '-' 2hexoct '-' 6hexoct
// hashlike := 12hexoct
// braced := '{' plain '}'
// urn := URN ':' UUID-NID ':' plain
// URN := 'urn'
// UUID-NID := 'uuid'
// 12hexoct := 6hexoct 6hexoct
// 6hexoct := 4hexoct 2hexoct
// 4hexoct := 2hexoct 2hexoct
// 2hexoct := hexoct hexoct
// hexoct := hexdig hexdig
// hexdig := '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' |
// 'a' | 'b' | 'c' | 'd' | 'e' | 'f' |
// 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
Indeed, the braced hashlike UUID is not explicitly mentioned as supported, but the ABNF has the productions braced := '{' plain '}'
and plain := canonical | hashlike
, which suggests that braced hashlike should be supported. Right now, it is not.
An authoritative source for the aforementioned ABNF would be nice to have too, because it doesn't seem to be given by RFC 4122.
For what it's worth, various online UUID validators accept {6ba7b8109dad11d180b400c04fd430c8}
.
The current example should be improved. Currently, that code does not compile, and it executes the final fmt.Printf("Successfully parsed: %s", u2)
unconditionally.
Aside from that, in the imports, we should add a newline between "fmt"
and "github.com/gofrs/uuid"
, since it is customary to separate standard library and third party imports with a blank line.
This ensures that users can import it as a /v3 module without needing the +incompatible go mod syntax.
Some consumers of this package may want to generate V1
UUIDs without exposing their physical device's hardware address to consumers of that UUID. We should look at exposing this functionality in some capacity for consumers.
See the issue on the original repo for more details (satori/go.uuid#64).
/cc @alessandrozucca
It seems like exposing the generator itself, and allowing people to provide their own HWAddr function should support most of what's needed here.
The function is currently deprecated and slated for removal in v3.0.0
. Not sure when we will release v3.0.0
, but this is here to serve as a reminder.
Because two values of a UUID
(array) type are directly comparable, the Equal()
function is superfluous. We should add a deprecation notice to the function comment, with the intent to remove it in v3.0.0.
go: github.com/gofrs/[email protected]+incompatible: Get "https://proxy.golang.org/github.com/gofrs/uuid/@v/v4.2.0+incompatible.mod": dial tcp 142.251.42.241:443: connectex: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
Can we add a go.mod
file with module github.com/gofrs/uuid/v3
?
It will help to test the new import path with major version and remove the actual ugly +incompatible
in go.mod
when we go1.11 get github.com/gofrs/uuid
The documentation for https://godoc.org/github.com/gofrs/uuid#Equal could be improved. While we're at it, perhaps the implementation could simply return u1 == u2
.
The SQL Value()
gives a string representation of UUID when called. However, storing UUIDs as bytes may be more efficient for some databases.
Other UUID libraries have the same issue: google/uuid#20
Would it be possible to have an option to either set globally to output bytes or a similar approach used for NullUUID
?
I'd be glad to work on a patch in either direction if necessary.
uuid.UUID.Value
is not implemented with pointer receiver,
therefore it panics when passing nil values to an SQL query.
value method github.com/gofrs/uuid/v3.UUID.Value called using nil *UUID pointer
I floated this idea very roughly in the #gofrs Slack channel, and it's to effectively rename this repository to avoid the Semantic Import Versioning (SIV) component of Go Modules
When this repository was forked from github.com/sator/go.uuid
, we chose to keep the same versioning scheme as the original project to help the migration be easier for folks. We did not need to consider Go Modules at the time, and so it was easy to start the project at a major version higher than the original project and assume it was low cost to do a major version increase as necessary.
Unfortunately, Go Modules has changed the situation, and so with hindsight it would have been better to not follow the versioning of the original project and to instead release as a v0.x
version.
We would create a new repository, github.com/gofrs/uuid.go
, and push the master
branch of this repository to that one. We would not push any of the tags from this repo there. We'd then create a new tag, v0.4.2
, at the same commit† as v4.2.0
of this repo. We would then update the README of this repo to point there, and archive the project. Any new development would happen there on v0.
† same commit + addition of go.mod
file / any updates for the rename
Hello,
What is the status of this repo? I see some PRs unmerged 1y old.
I am interested to update or write a new implementation for V6-7 UUIDs (v4 draft including the distributed requirements) and wondering if I can contribute to this project or create another one.
Is it possible to generated cryptographically strong uuid values?
I think https://godoc.org/github.com/gofrs/uuid#Equal should say "Nil is the nil UUID...".
https://godoc.org/github.com/gofrs/uuid#UUID.UnmarshalText should mention the braced hashlike format, as described in #14, and the URN hashlike format as in
Lines 131 to 134 in 57be146
Perhaps https://godoc.org/github.com/gofrs/uuid#DefaultGenerator could be placed outside the var
block it is currently in, standing alone instead, to reduce noise and to promote the comment to a "proper Godoc" rather than code comment.
Perhaps the comment on https://godoc.org/github.com/gofrs/uuid#UUID could also be improved. It feels like it needs a verb.
This is an issue to gather input about doing an engagement of some larger projects who use github.com/satori/go.uuid
to get them moved over to our repo. Should we wait until the Modules stuff shakes out/we cut the next major version?
The idea would be to open issues on the projects, at a minimum, to suggest they change. We could additionally then issue PRs, time permitting, to some of those projects to update them to point to us. All worth considering / discussing.
@gofrs/all thoughts?
As discussed in the #gofrs Slack channel, perhaps we finally have a resolution for #61.
The plan is to de-virtualize the /v3
, remove go.mod
from the project root, and add forwarding declarations and type aliases in the /v3
subdirectory, followed by cutting v3.2.0.
If anyone is willing to do this work and submit it for review, that would be great. Please ping me when you do. I had previously sent c6f696b which is the other way around. There, the forwarding package is the root package, while /v3
contains the actual code. Perhaps it would be good to base the work on that commit, but we want to do it the other way around. The root package should be the canonical one, and we bite the bullet for a while to support existing modules users using the /v3
subdirectory.
What happens with a potential v4.0.0 in the future remains to be seen.
Is the lack of UUID
embedding in NullUUID
by design?
I would expect it to be as close as possible of a drop-in replacement.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.