automerge

package module
v0.0.0-...-b7d9d51 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 13, 2024 License: MIT Imports: 10 Imported by: 12

README

automerge-go

automerge-go provides the ability to interact with automerge documents. It is a featureful wrapper around automerge-rs that uses cgo to avoid reimplementing the core engine from scratch.

For package documentation, see the Go documentation at https://pkg.go.dev/github.com/automerge/automerge-go.

Building from automerge-c

This step must be done on an Apple Silicon mac with docker running.

./deps/rebuild.sh

Documentation

Overview

Package automerge provides the ability to interact with automerge documents. It is a featureful wrapper around automerge-rs that uses cgo to avoid reimplementing the core engine from scratch.

Document Structure and Types

Automerge documents have a JSON-like structure, they consist of a root map which has string keys, and values of any supported types.

Supported types include several immutable primitive types:

  • bool
  • string, []byte
  • float64, int64, uint64
  • time.Time (in millisecond precision)
  • nil (untyped)

And four mutable automerge types:

  • Map - a mutable map[string]any
  • List - a mutable []any
  • Text – a mutable string
  • Counter – an int64 that is incremented (instead of overwritten) by collaborators

If you read part of the doc that has no value set, automerge-go will return a Value with Kind() == KindVoid. You cannot create such a Value directly or write one to the document.

On write automerge-go will attempt to convert provided values to the most appropriate type, and error if that is not possible. For example structs are maps are converted to *Map, slices and arrays to *List, most numeric types are converted to float64 (the default number type for automerge), with the exception of int64 and uint64.

On read automerge-go will return a *Value, and you can use As to convert this to a more useful type.

Interacting with the Document

Depending on your use-case there are a few ways to interact with the document, the recommended approach for reading is to cast the document to a go value:

doc, err := automerge.Load(bytes)
if err != nil { return err }

myVal, err := automerge.As[*myType](doc.Root())
if err != nil { return err }

If you wish to modify the document, or access just a subset, use a Path:

err := doc.Path("x", "y", 0).Set(&myStruct{Header: "h"})
v, err := automerge.As[*myStruct](doc.Path("x", "y", 0).Get())

It is always recommended to write the smallest change to the document, as this will improve the experience of other collaborative editors.

Writing to a path will create any intermediate Map or List objects needed, Reading from a path will not, but may return a void Value if the intermediate objects don't exist.

The automerge mutable types have additional methods. You can access these methods by calling Path.Map, Path.List, Path.Text or Path.Counter which assume the path is of the type you say it is:

values, err := doc.Path("collection").Map().Values()
fmt.Println(values)

When you do this, any errors caused by traversing the path will be returned from methods called on the returned objects.

Controling formatting of structs

By default automerge will convert your struct to a map. For each public field in the struct (the name starts with an uppercase letter) automerge will add an entry to the map with the name of the field and the fields value converted to an automerge value recursively.

You can control this behaviour using struct tags:

struct Example {
	Renamed bool `automerge:"newname"`
	Private bool `automerge:"-"`
}

If the tag is present and equal to "-" the field will be ignored by automerge, otherwise the fields name will be set to the value of the tag.

Syncing and concurrency

You can access methods on *Doc from multiple goroutines and access is mediated appropriately. For other types, you must provide your own syncronization, or only use them from one goroutine at a time.

If you retain a Map, List, Counter, or Text object while the document is being modified concurrently be aware that its value may change, or it may be deleted from the document. A safer pattern is to fork the document, make the changes you want, and then merge your changes back into the shared document.

There are a few different ways to keep distributed automerge docs in sync. If you're mostly making changes in one place and syncing them to another, you can use Doc.SaveIncremental and Doc.LoadIncremental

//* process 1 *
initBytes, err := doc.Save()
for {
	// ... make changes ...
	bytes, err := doc.SaveIncremental()
	ch <- bytes
}

//* process 2*
err := automerge.Load(initBytes)
for bytes := range ch {
	err := doc.LoadIncremental(bytes)
}

If both peers are making changes you can use a SyncState object to keep them in sync. This wraps an underlying efficient sync protocol to minimize both round-trips and bandwidth used.

//* process 1 *
syncState := automerge.NewSyncState(doc)
for {
	m, valid := syncState.GenerateMessage()
	if valid {
		sendCh <- m.Bytes()
	}

	msg := <-recvCh
	_, err := syncState.ReceiveMessage(msg)
	if err != nil {
		panic(err)
	}
}

//* process 2 *
syncState := automerge.NewSyncState(doc)
for {
	msg := <-sendCh
	_, err := syncState.ReceiveMessage(msg)
	if err != nil {
		panic(err)
	}

	m, valid := syncState.GenerateMessage()
	if valid {
		recvCh <- m.Bytes()
	}
}

If you need more flexibility, you can use Doc.Changes and Doc.Apply to manually track the changes you want to transfer. This puts more burden on the implementor to ensure an absense of bugs.

//* process 1 *
heads := doc.Heads()
for {
	// ... make changes ...
	changes, err := doc.Changes(heads)
	heads = doc.Heads()
	bytes := changes.Save()
	ch <- bytes
}

//* process 2 *
for bytes := range ch {
	changes, err := automerge.LoadChanges(bytes)
	err := doc.Apply(changes)
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func As

func As[T any](v *Value, errs ...error) (ret T, err error)

As converts v to type T. If the v cannot be converted to T, an error will be returned. T can be any of the automerge builtin types (*Map, *List, *Counter, *Text), or any type that v's underlying value could be converted to. This conversion works generously, so that (for example) T could be any numeric type that v's value fits in, or if v.IsNull() then the 0-value of T will be returned.

To make it easier to wrap a call to Get(), when an not-nil error is passed as a second argument, As will return (nil, err)

Example
doc := automerge.New()
doc.Path("isValid").Set(true)
doc.Path("foo", "bar").Set("baz")

b, err := automerge.As[bool](doc.Path("isValid").Get())
if err != nil {
	panic(err)
}
fmt.Println("isValid:", b == true)

v, err := automerge.As[string](doc.Path("foo", "bar").Get())
if err != nil {
	panic(err)
}
fmt.Println("foo-bar:", v)

type S struct {
	IsValid bool `automerge:"isValid"`
}
s, err := automerge.As[*S](doc.Root())
if err != nil {
	panic(err)
}
fmt.Println("root valid:", s.IsValid == true)
Output:

isValid: true
foo-bar: baz
root valid: true

func NewActorID

func NewActorID() string

NewActorID generates a new unique actor id.

func SaveChanges

func SaveChanges(cs []*Change) []byte

SaveChanges saves multiple changes to bytes (see also LoadChanges)

Types

type Change

type Change struct {
	// contains filtered or unexported fields
}

Change is a set of mutations to the document. It is analagous to a commit in a version control system like Git.

func LoadChanges

func LoadChanges(raw []byte) ([]*Change, error)

LoadChanges loads changes from bytes (see also SaveChanges and Change.Save)

func (*Change) ActorID

func (c *Change) ActorID() string

ActorID identifies the actor that made the change hex-encoded

func (*Change) ActorSeq

func (c *Change) ActorSeq() uint64

ActorSeq is 1 for the first change by a given actor, 2 for the next, and so on.

func (*Change) Dependencies

func (c *Change) Dependencies() []ChangeHash

Dependencies returns the hashes of all changes that this change directly depends on.

func (*Change) Hash

func (c *Change) Hash() ChangeHash

Hash identifies the change by the SHA-256 of its binary representation

func (*Change) Message

func (c *Change) Message() string

Message returns the commit message (if any)

func (*Change) Save

func (c *Change) Save() []byte

Save exports the change for transferring between systems

func (*Change) Timestamp

func (c *Change) Timestamp() time.Time

Timestamp returns the commit time (or the zero time if one was not set)

type ChangeHash

type ChangeHash [32]byte

ChangeHash is a SHA-256 hash identifying an automerge change. Like a git commit, the hash encompasses both the changes made, any metadata (like commit message, or timestamp) and any changes on which this change depends.

func NewChangeHash

func NewChangeHash(s string) (ChangeHash, error)

NewChangeHash creates a change has from its hex representation.

func (ChangeHash) String

func (ch ChangeHash) String() string

String returns the hex-encoded form of the change hash

type CommitOptions

type CommitOptions struct {
	Time       *time.Time
	AllowEmpty bool
}

CommitOptions are (rarer) options passed to commit. If Time is not set then time.Now() is used. To omit a timestamp pass a pointer to the zero time: &time.Time{} If AllowEmpty is not set then commits with no operations will error.

type Counter

type Counter struct {
	// contains filtered or unexported fields
}

Counter is a mutable int64 that collaborators can increment or decrement.

func NewCounter

func NewCounter(v int64) *Counter

NewCounter returns a detached counter with the given starting value. Before you can call Counter.Get or Counter.Inc you must write it to the document.

func (*Counter) Get

func (c *Counter) Get() (int64, error)

Get returns the current value of the counter.

func (*Counter) GoString

func (c *Counter) GoString() string

GoString returns a representation suitable for debugging.

func (*Counter) Inc

func (c *Counter) Inc(delta int64) error

Inc adjusts the counter by delta.

func (*Counter) String

func (c *Counter) String() string

String returns a representation suitable for debugging.

type Doc

type Doc struct {
	// contains filtered or unexported fields
}

Doc represents an automerge document. You can read and write the values of the document with Doc.Root, Doc.RootMap or Doc.Path, and other methods are provided to enable collaboration and accessing historical data. After writing to the document you should immediately call Doc.Commit to explicitly create a Change, though if you forget to do this most methods on a document will create an anonymous change on your behalf.

func Load

func Load(b []byte) (*Doc, error)

Load loads a document from its serialized form

func New

func New() *Doc

New creates a new empty document

func (*Doc) ActorID

func (d *Doc) ActorID() string

ActorID returns the current actorId of the doc hex-encoded This is used for all operations that write to the document. By default a random ActorID is generated, but you can customize this with Doc.SetActorID.

func (*Doc) Apply

func (d *Doc) Apply(chs ...*Change) error

Apply the given change(s) to the document

func (*Doc) Change

func (d *Doc) Change(ch ChangeHash) (*Change, error)

Change gets a specific change by hash.

func (*Doc) Changes

func (d *Doc) Changes(since ...ChangeHash) ([]*Change, error)

Changes returns all changes made to the doc since the given heads. If since is empty, returns all changes to recreate the document.

func (*Doc) Commit

func (d *Doc) Commit(msg string, opts ...CommitOptions) (ChangeHash, error)

Commit adds a new version to the document with all operations so far. The returned ChangeHash is the new head of the document. Note: You should call commit immediately after modifying the document as most methods that inspect or modify the documents' history will automatically commit any outstanding changes.

func (*Doc) Fork

func (d *Doc) Fork(asOf ...ChangeHash) (*Doc, error)

Fork returns a new, independent, copy of the document if asOf is empty then it is forked in its current state. otherwise it returns a version as of the given heads.

func (*Doc) Heads

func (d *Doc) Heads() []ChangeHash

Heads returns the hashes of the current heads for the document. For a new document with no changes, this will have length zero. If you have just created a commit, this will have length one. If you have applied independent changes from multiple actors, then the length will be greater that one. If you'd like to merge independent changes together call Doc.Commit passing a CommitOptions with AllowEmpty set to true.

func (*Doc) LoadIncremental

func (d *Doc) LoadIncremental(raw []byte) error

LoadIncremental applies the changes exported by Doc.SaveIncremental. It is the callers responsibility to ensure that every incremental change is applied to keep the documents in sync. See also SyncState for a more managed approach to syncing.

func (*Doc) Merge

func (d *Doc) Merge(d2 *Doc) ([]ChangeHash, error)

Merge extracts all changes from d2 that are not in d and then applies them to d.

func (*Doc) Path

func (d *Doc) Path(path ...any) *Path

Path returns a *Path that points to a position in the doc. Path will panic unless each path component is a string or an int. Calling Path with no arguments returns a path to the Doc.Root.

func (*Doc) Root

func (d *Doc) Root() *Value

Root returns the root of the document as a Value of KindMap

func (*Doc) RootMap

func (d *Doc) RootMap() *Map

RootMap returns the root of the document as a Map

func (*Doc) Save

func (d *Doc) Save() []byte

Save exports a document to its serialized form

func (*Doc) SaveIncremental

func (d *Doc) SaveIncremental() []byte

SaveIncremental exports the changes since the last call to Doc.Save or Doc.SaveIncremental for passing to Doc.LoadIncremental on a different doc. See also SyncState for a more managed approach to syncing.

func (*Doc) SetActorID

func (d *Doc) SetActorID(id string) error

SetActorID updates the current actorId of the doc. Valid actor IDs are a string with an even number of hex-digits.

type Kind

type Kind uint

Kind represents the underlying type of a Value

var (
	// KindVoid indicates the value was not present
	KindVoid Kind = C.AM_VAL_TYPE_VOID
	// KindBool indicates a bool
	KindBool Kind = C.AM_VAL_TYPE_BOOL
	// KindBytes indicates a []byte
	KindBytes Kind = C.AM_VAL_TYPE_BYTES
	// KindCounter indicates an *automerge.Counter
	KindCounter Kind = C.AM_VAL_TYPE_COUNTER
	// KindFloat64 indicates a float64
	KindFloat64 Kind = C.AM_VAL_TYPE_F64
	// KindInt indicates an int
	KindInt64 Kind = C.AM_VAL_TYPE_INT
	// KindUint indicates a uint
	KindUint64 Kind = C.AM_VAL_TYPE_UINT
	// KindNull indicates an explicit null was present
	KindNull Kind = C.AM_VAL_TYPE_NULL
	// KindStr indicates a string
	KindStr Kind = C.AM_VAL_TYPE_STR
	// KindTime indicates a time.Time
	KindTime Kind = C.AM_VAL_TYPE_TIMESTAMP
	// KindUnknown indicates an unknown type from a future version of automerge
	KindUnknown Kind = C.AM_VAL_TYPE_UNKNOWN

	// KindMap indicates an *automerge.Map
	KindMap Kind = kindObjType | C.AM_OBJ_TYPE_MAP
	// KindList indicates an *automerge.List
	KindList Kind = kindObjType | C.AM_OBJ_TYPE_LIST
	// KindText indicates an *automerge.Text
	KindText Kind = kindObjType | C.AM_OBJ_TYPE_TEXT
)

func (Kind) String

func (k Kind) String() string

String returns a human-readable representation of the Kind

type List

type List struct {
	// contains filtered or unexported fields
}

List is an automerge type that stores a list of Value's

func NewList

func NewList() *List

NewList returns a detached list. Before you can read from or write to it you must write it to the document.

func (*List) Append

func (l *List) Append(values ...any) error

Append adds the values at the end of the list.

func (*List) Delete

func (l *List) Delete(idx int) error

Delete removes the value at idx and shortens the list.

func (*List) Get

func (l *List) Get(i int) (*Value, error)

Get returns the value at index i

func (*List) GoString

func (l *List) GoString() string

GoString returns a representation suitable for debugging.

func (*List) Insert

func (l *List) Insert(idx int, value ...any) error

Insert inserts the new values just before idx.

func (*List) Len

func (l *List) Len() int

Len returns the length of the list, or 0 on error

func (*List) Set

func (l *List) Set(idx int, value any) error

Set overwrites the value at l[idx] with value.

func (*List) String

func (l *List) String() string

String returns a representation suitable for debugging.

func (*List) Values

func (l *List) Values() ([]*Value, error)

Values returns a slice of the values in a list

type Map

type Map struct {
	// contains filtered or unexported fields
}

Map is an automerge type that stores a map of strings to values

func NewMap

func NewMap() *Map

NewMap returns a detached map. Before you can read from or write to it you must write it to the document.

func (*Map) Delete

func (m *Map) Delete(key string) error

Delete deletes a key and its corresponding value from the map

func (*Map) Get

func (m *Map) Get(key string) (*Value, error)

Get retrieves the value from the map. This method will return an error if the underlying Get operation fails, or if this is the first attempt to access a Path.Map() and the path is not traverseable

func (*Map) GoString

func (m *Map) GoString() string

GoString returns a representation suitable for debugging.

func (*Map) Keys

func (m *Map) Keys() ([]string, error)

Keys returns the current list of keys for the map

func (*Map) Len

func (m *Map) Len() int

Len returns the number of keys set in the map, or 0 on error

func (*Map) Set

func (m *Map) Set(key string, value any) error

Set sets a key in the map to a given value. This method may error if the underlying operation errors, the type you provide cannot be converted to an automerge type, or if this is the first write to a Path.Map and the path is not traverseable.

func (*Map) String

func (m *Map) String() string

String returns a representation suitable for debugging.

func (*Map) Values

func (m *Map) Values() (map[string]*Value, error)

Values returns the values of the map

type Path

type Path struct {
	// contains filtered or unexported fields
}

Path is a cursor that lets you reach into the document

func (*Path) Counter

func (p *Path) Counter() *Counter

Counter assumes there is a Counter at the given path. Calling methods on the counter will error if the path cannot be traversed or if the value at this path is not a counter.

func (*Path) Delete

func (p *Path) Delete() error

Delete removes the value at this path from the document.

func (*Path) Get

func (p *Path) Get() (*Value, error)

Get returns the value at a given path

func (*Path) GoString

func (p *Path) GoString() string

GoString returns a representation suitable for debugging

func (*Path) List

func (p *Path) List() *List

List assumes there is a List at the given path. Calling methods on the list will error if the path cannot be traversed or if the value at this path is not a list. If there is a void at this location, reading from the list will return void, and writing to the list will implicitly create it (and the path as necesasry).

func (*Path) Map

func (p *Path) Map() *Map

Map assumes there is a Map at the given path. Calling methods on the map will error if the path cannot be traversed or if the value at this path is not a map. If there is a void at this location, writing to this map will implicitly create it (and the path as necessary).

func (*Path) Path

func (p *Path) Path(path ...any) *Path

Path extends the cursor with more path segments. It panics if any path segment is not a string or an int. It does not check that the path segment is traversable until you call a method that accesses the document.

func (*Path) Set

func (p *Path) Set(v any) error

Set sets the value at the given path, and creates any missing parent Maps or Lists needed.

func (*Path) String

func (p *Path) String() string

String returns a representation suitable for debugging.

func (*Path) Text

func (p *Path) Text() *Text

Text assumes there is a Text at the given path. Calling methods on the counter will error if the path cannot be traversed or if the value at this path is not a counter.

type SyncMessage

type SyncMessage struct {
	// contains filtered or unexported fields
}

SyncMessage is sent between peers to keep copies of a document in sync.

func (*SyncMessage) Bytes

func (sm *SyncMessage) Bytes() []byte

Bytes returns a representation for sending over the network.

func (*SyncMessage) Changes

func (sm *SyncMessage) Changes() []*Change

Changes returns any changes included in this SyncMessage

func (*SyncMessage) Heads

func (sm *SyncMessage) Heads() []ChangeHash

Heads gives the heads of the peer that generated the SyncMessage

type SyncState

type SyncState struct {
	Doc *Doc
	// contains filtered or unexported fields
}

SyncState represents the state of syncing between a local copy of a doc and a peer; and lets you optimize bandwidth used to ensure two docs are always in sync.

Example
doc := automerge.New()
syncState := automerge.NewSyncState(doc)

docUpdated := make(chan bool)
recv := make(chan []byte)
send := make(chan []byte)

loop:
// generate an initial message, and then do so again
// after receiving updates from the peer or making local changes
for {
	msg, valid := syncState.GenerateMessage()
	if valid {
		send <- msg.Bytes()
	}

	select {
	case msg, ok := <-recv:
		if !ok {
			break loop
		}

		_, err := syncState.ReceiveMessage(msg)
		if err != nil {
			panic(err)
		}

	case _, ok := <-docUpdated:
		if !ok {
			break loop
		}
	}
}
Output:

func LoadSyncState

func LoadSyncState(d *Doc, raw []byte) (*SyncState, error)

LoadSyncState lets you resume syncing with a peer from where you left off.

func NewSyncState

func NewSyncState(d *Doc) *SyncState

NewSyncState returns a new sync state to sync with a peer

func (*SyncState) GenerateMessage

func (ss *SyncState) GenerateMessage() (sm *SyncMessage, valid bool)

GenerateMessage generates the next message to send to the client. If `valid` is false the clients are currently in sync and there are no more messages to send (until you either modify the underlying document)

func (*SyncState) ReceiveMessage

func (ss *SyncState) ReceiveMessage(msg []byte) (*SyncMessage, error)

ReceiveMessage should be called with every message created by GenerateMessage on the peer side.

func (*SyncState) Save

func (ss *SyncState) Save() []byte

Save serializes the sync state so that you can resume it later. This is an optimization to reduce the number of round-trips required to get two peers in sync at a later date.

type Text

type Text struct {
	// contains filtered or unexported fields
}

Text is a mutable unicode string that can be edited collaboratively.

Note that automerge considers text to be a sequence of unicode codepoints while most go code treats strings as a sequence of bytes (that are hopefully valid utf8). In go programs unicode codepoints are stored as integers of type rune, and the unicode/utf8 package provides some helpers for common operations.

When editing Text you must pass positions and counts in terms of codepoints not bytes. For example if you wanted to replace the first instance of "🙃" you could do something like this:

s, _ := text.Get() => "😀🙃"
byteIndex := strings.Index(s, "🙃") => 4
runeIndex := utf8.RuneCountInString(s[:byteIndex]) => 1
text.Splice(runeIndex, 1, "🧟") => "🙃🧟"

Although it is possible to represent invalid utf8 in a go string, automerge will error if you try to write invalid utf8 into a document.

If you are new to unicode it's worth pointing out that the number of codepoints does not necessarily correspond to the number of rendered glyphs (for example Text("👍🏼").Len() == 2). For more information consult the Unicode Consortium's FAQ.

func NewText

func NewText(s string) *Text

NewText returns a detached Text with the given starting value. Before you can read or write it you must write it to the document.

func (*Text) Append

func (t *Text) Append(s string) error

Append adds substr s at the end of the string

func (*Text) Delete

func (t *Text) Delete(pos int, del int) error

Delete deletes del runes from position pos

func (*Text) Get

func (t *Text) Get() (string, error)

Get returns the current value as a string

func (*Text) GoString

func (t *Text) GoString() string

GoString returns a representation suitable for debugging.

func (*Text) Insert

func (t *Text) Insert(pos int, s string) error

Insert adds a substr at position pos in the Text

func (*Text) Len

func (t *Text) Len() int

Len returns number of unicode codepoints in the text, this may be less than the number of utf-8 bytes. For example Text("😀😀").Len() == 2, while len("😀😀") == 8.

func (*Text) Set

func (t *Text) Set(s string) error

Set overwrites the entire string with a new value, prefer to use Insert/Delete/Append/Splice as appropriate to preserves collaborators changes.

func (*Text) Splice

func (t *Text) Splice(pos int, del int, s string) error

Splice deletes del runes at position pos, and inserts substr s in their place.

func (*Text) String

func (t *Text) String() string

String returns a representation suitable for debugging.

type Value

type Value struct {
	// contains filtered or unexported fields
}

Value represents a dynamically typed value read from a document. It can hold any of the supported primative types (bool, string, []byte, float64, int64, uint64, time.Time) the four mutable types (*Map, *List, *Text, *Counter), or it can be an explicit null, or a void to indicate that no value existed at all. You can convert from a Value to a go type using As, or call accessor methods directly.

func (*Value) Bool

func (v *Value) Bool() bool

Bool returns the value as a bool, it panics if Kind() != KindBool

func (*Value) Bytes

func (v *Value) Bytes() []byte

Bytes returns the Value as a []byte, it panics if Kind() != KindBytes

func (*Value) Counter

func (v *Value) Counter() *Counter

Counter returns the value as a *Counter, it panics if Kind() != KindCounter

func (*Value) Float64

func (v *Value) Float64() float64

Float64 returns the value as a float64, it panics if Kind() != KindFloat64

func (*Value) GoString

func (v *Value) GoString() string

GoString returns a representation suitable for debugging.

func (*Value) Int64

func (v *Value) Int64() int64

Int64 returns the value as a int64, it panics if Kind() != KindInt64

func (*Value) Interface

func (v *Value) Interface() any

Interface returns the value as a go interface. It recursively converts automerge.Map to map[string]any, automerge.List to []any, automerge.Text to string, and automerge.Counter to int64.

func (*Value) IsNull

func (v *Value) IsNull() bool

IsNull returns true if the value is null

func (*Value) IsUnknown

func (v *Value) IsUnknown() bool

IsUnknown returns true if the type of the value was unknown

func (*Value) IsVoid

func (v *Value) IsVoid() bool

IsVoid returns true if the value did not exist in the document

func (*Value) Kind

func (v *Value) Kind() Kind

Kind reports the kind of the value

func (*Value) List

func (v *Value) List() *List

List returns the value as a *List, it panics if Kind() != KindList

func (*Value) Map

func (v *Value) Map() *Map

Map returns the value as a *Map, it panics if Kind() != KindMap

func (*Value) Str

func (v *Value) Str() string

Str returns the Value as a string, it panics if Kind() != KindStr

func (*Value) String

func (v *Value) String() string

String returns a representation suitable for debugging. Use Value.Str to get the underlying string.

func (*Value) Text

func (v *Value) Text() *Text

Text returns the value as a *Text, it panics if Kind() != KindText

func (*Value) Time

func (v *Value) Time() time.Time

Time returns the value as a time.Time, it panics if Kind() != KindTime

func (*Value) Uint64

func (v *Value) Uint64() uint64

Uint64 returns the value as a uint64, it panics if Kind() != KindUint64

Directories

Path Synopsis
cmd
Package deps exists because shared libraries must be in the same directory as a go package for `go mod vendor` to work.
Package deps exists because shared libraries must be in the same directory as a go package for `go mod vendor` to work.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL