nulled

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

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

Go to latest
Published: Jan 9, 2026 License: BSD-3-Clause Imports: 8 Imported by: 0

README

English | 简体中文

NullED

Null Value Encode/Decode

nulled is a Go library that provides nullable types for bool, float64, int64, string, and time.Time. It is built as a wrapper around the popular gopkg.in/guregu/null.v4 library, extending it with additional functionality and convenience methods.

This library is particularly useful for handling nullable values from databases, JSON/YAML APIs, or any other source where a value can be either present or null.

Features

  • Provides nullable Bool, Float, Int, String, and Time types.
  • Seamlessly handles JSON encoding and decoding (json.Marshaler, json.Unmarshaler).
  • Implements sql.Scanner and driver.Valuer for easy database integration.
  • Supports text encoding and decoding (encoding.TextUnmarshaler).
  • Supports Gob encoding and decoding (gob.GobEncoder, gob.GobDecoder).
  • Helper functions to create nullable types from values and pointers.
  • Methods to safely retrieve values or a zero-value if null (ValueOrZero).
  • EncodeValues method for encoding values into net/url.Values.
  • NullValue method to get the underlying gopkg.in/guregu/null.v4 type.

Installation

To install the nulled package, use go get:

go get github.com/hiscaler/nulled

Usage

Here are some examples of how to use the different nullable types provided by this library.

String
package main

import (
	"encoding/json"
	"fmt"
	"github.com/hiscaler/nulled"
)

func main() {
	// Valid string
	s1 := nulled.StringFrom("Hello, World!")
	fmt.Printf("s1: Value=%q, Valid=%t\n", s1.ValueOrZero(), s1.Valid)

	// Null string (from empty string)
	s2 := nulled.StringFrom("")
	fmt.Printf("s2: Value=%q, Valid=%t\n", s2.ValueOrZero(), s2.Valid)

	// JSON Marshalling
	jsonData, _ := json.Marshal(struct {
		S1 nulled.String
		S2 nulled.String
	}{S1: s1, S2: s2})
	fmt.Println("JSON:", string(jsonData)) // JSON: {"S1":"Hello, World!","S2":null}
}
Int
package main

import (
	"encoding/json"
	"fmt"
	"github.com/hiscaler/nulled"
)

func main() {
	// Valid int
	i1 := nulled.IntFrom(123)
	fmt.Printf("i1: Value=%d, Valid=%t\n", i1.ValueOrZero(), i1.Valid)

	// Null int (from pointer)
	var p *int64
	i2 := nulled.IntFromPtr(p)
	fmt.Printf("i2: Value=%d, Valid=%t\n", i2.ValueOrZero(), i2.Valid)

	// JSON Marshalling
	jsonData, _ := json.Marshal(struct {
		I1 nulled.Int
		I2 nulled.Int
	}{I1: i1, I2: i2})
	fmt.Println("JSON:", string(jsonData)) // JSON: {"I1":123,"I2":null}
}
Float
package main

import (
	"encoding/json"
	"fmt"
	"github.com/hiscaler/nulled"
)

func main() {
	// Valid float
	f1 := nulled.FloatFrom(123.45)
	fmt.Printf("f1: Value=%f, Valid=%t\n", f1.ValueOrZero(), f1.Valid)

	// Null float
	f2 := nulled.NewFloat(0, false)
	fmt.Printf("f2: Value=%f, Valid=%t\n", f2.ValueOrZero(), f2.Valid)

	// JSON Marshalling
	jsonData, _ := json.Marshal(struct {
		F1 nulled.Float
		F2 nulled.Float
	}{F1: f1, F2: f2})
	fmt.Println("JSON:", string(jsonData)) // JSON: {"F1":123.45,"F2":null}
}
Bool
package main

import (
	"encoding/json"
	"fmt"
	"github.com/hiscaler/nulled"
)

func main() {
	// Valid bool
	b1 := nulled.BoolFrom(true)
	fmt.Printf("b1: Value=%t, Valid=%t\n", b1.ValueOrZero(), b1.Valid)

	// Null bool
	b2 := nulled.NewBool(false, false)
	fmt.Printf("b2: Value=%t, Valid=%t\n", b2.ValueOrZero(), b2.Valid)

	// JSON Marshalling
	jsonData, _ := json.Marshal(struct {
		B1 nulled.Bool
		B2 nulled.Bool
	}{B1: b1, B2: b2})
	fmt.Println("JSON:", string(jsonData)) // JSON: {"B1":true,"B2":null}
}
Time
package main

import (
	"encoding/json"
	"fmt"
	"github.com/hiscaler/nulled"
	"time"
)

func main() {
	// Valid time
	t1 := nulled.TimeFrom(time.Now())
	fmt.Printf("t1: Value=%s, Valid=%t\n", t1.ValueOrZero(), t1.Valid)

	// Null time
	var p *time.Time
	t2 := nulled.TimeFromPtr(p)
	fmt.Printf("t2: Value=%s, Valid=%t\n", t2.ValueOrZero(), t2.Valid)

	// JSON Marshalling
	jsonData, _ := json.Marshal(struct {
		T1 nulled.Time
		T2 nulled.Time
	}{T1: t1, T2: t2})
	fmt.Println("JSON:", string(jsonData))
}

Database Integration

All nulled types implement the database/sql.Scanner and database/sql/driver.Valuer interfaces, making them compatible with database/sql out of the box.

Scanning a Null Value

When you scan a NULL value from a database, the nulled type will be marked as invalid (Valid: false).

var name nulled.String
err := db.QueryRow("SELECT name FROM users WHERE id = 1").Scan(&name)
// If the 'name' column is NULL, name.Valid will be false.
Storing a Null Value

To store a NULL value in the database, you can use a nulled type that is not valid.

invalidName := nulled.NewString("", false)
_, err := db.Exec("UPDATE users SET name = ? WHERE id = 1", invalidName)
// This will set the 'name' column to NULL.

gopkg.in/guregu/null.v4 Compatibility

To maintain compatibility with the underlying gopkg.in/guregu/null.v4 library, each nulled type has a NullValue() method that returns the corresponding null.v4 type.

import "gopkg.in/guregu/null.v4"

// Get the underlying null.v4 type
nulledString := nulled.StringFrom("hello")
nullV4String := nulledString.NullValue() // This is a null.String

// You can use it with functions that expect a null.v4 type
func processNullV4(s null.String) {
    // ...
}
processNullV4(nullV4String)

Integration with go-querystring/query

The nulled types can be seamlessly integrated with github.com/google/go-querystring/query to encode structs into URL query parameters. This is facilitated by the EncodeValues method implemented on each nulled type, which correctly handles valid and null values.

First, ensure you have go-querystring installed:

go get github.com/google/go-querystring/query

Here's an example:

package main

import (
	"fmt"
	"net/url"
	"time"

	"github.com/google/go-querystring/query"
	"github.com/hiscaler/nulled"
)

type MyQueryParams struct {
	Name    nulled.String `url:"name"`
	Age     nulled.Int    `url:"age"`
	Active  nulled.Bool   `url:"active"`
	Amount  nulled.Float  `url:"amount"`
	Created nulled.Time   `url:"created"`
	Search  nulled.String `url:"search,omitempty"` // omitempty will skip if null or empty
}

func main() {
	params := MyQueryParams{
		Name:    nulled.StringFrom("John Doe"),
		Age:     nulled.IntFrom(30),
		Active:  nulled.BoolFrom(true),
		Amount:  nulled.FloatFrom(123.45),
		Created: nulled.TimeFrom(time.Date(2023, 1, 15, 10, 30, 0, 0, time.UTC)),
		Search:  nulled.StringFrom("Go Lang"),
	}

	v, _ := query.Values(params)
	fmt.Println("Query with all valid values:", v.Encode())
	// Output: Query with all valid values: active=true&age=30&amount=123.45&created=2023-01-15+10%3A30%3A00&name=John+Doe&search=Go+Lang

	nullParams := MyQueryParams{
		Name:    nulled.NewString("", false), // Null string
		Age:     nulled.NewInt(0, false),    // Null int
		Active:  nulled.NewBool(false, false), // Null bool
		Amount:  nulled.NewFloat(0, false),  // Null float
		Created: nulled.NewTime(time.Time{}, false), // Null time
		Search:  nulled.NewString("", false), // Null string with omitempty
	}

	nv, _ := query.Values(nullParams)
	fmt.Println("Query with null values:", nv.Encode())
	// Output: Query with null values:
}

Contributing

Contributions are welcome! Please feel free to submit a pull request or open an issue.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Bool

type Bool null.Bool

func BoolFrom

func BoolFrom(b bool) Bool

func BoolFromPtr

func BoolFromPtr(b *bool) Bool

func NewBool

func NewBool(b bool, valid bool) Bool

func (Bool) EncodeValues

func (b Bool) EncodeValues(key string, v *url.Values) error

func (*Bool) GobDecode

func (b *Bool) GobDecode(data []byte) error

func (Bool) GobEncode

func (b Bool) GobEncode() ([]byte, error)

func (Bool) MarshalJSON

func (b Bool) MarshalJSON() ([]byte, error)

func (Bool) NullValue

func (b Bool) NullValue() null.Bool

func (*Bool) UnmarshalJSON

func (b *Bool) UnmarshalJSON(data []byte) error

func (*Bool) UnmarshalText

func (b *Bool) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (Bool) ValueOrZero

func (b Bool) ValueOrZero() bool

type Float

type Float null.Float

func FloatFrom

func FloatFrom(i float64) Float

func FloatFromPtr

func FloatFromPtr(f *float64) Float

func NewFloat

func NewFloat(i float64, valid bool) Float

func (Float) EncodeValues

func (f Float) EncodeValues(key string, v *url.Values) error

func (*Float) GobDecode

func (f *Float) GobDecode(data []byte) error

func (Float) GobEncode

func (f Float) GobEncode() ([]byte, error)

func (Float) MarshalJSON

func (f Float) MarshalJSON() ([]byte, error)

func (Float) NullValue

func (f Float) NullValue() null.Float

func (*Float) UnmarshalJSON

func (f *Float) UnmarshalJSON(data []byte) error

func (*Float) UnmarshalText

func (f *Float) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (Float) ValueOrZero

func (f Float) ValueOrZero() float64

type Int

type Int null.Int

func IntFrom

func IntFrom(i int64) Int

func IntFromPtr

func IntFromPtr(i *int64) Int

func NewInt

func NewInt(i int64, valid bool) Int

func (Int) EncodeValues

func (i Int) EncodeValues(key string, v *url.Values) error

func (*Int) GobDecode

func (i *Int) GobDecode(data []byte) error

GobDecode implements the gob.GobDecoder interface.

func (Int) GobEncode

func (i Int) GobEncode() ([]byte, error)

GobEncode implements the gob.GobEncoder interface.

func (Int) MarshalJSON

func (i Int) MarshalJSON() ([]byte, error)

func (Int) NullValue

func (i Int) NullValue() null.Int

func (*Int) UnmarshalJSON

func (i *Int) UnmarshalJSON(bytes []byte) error

func (Int) ValueOrZero

func (i Int) ValueOrZero() int64

type String

type String null.String

func NewString

func NewString(s string, valid bool) String

func StringFrom

func StringFrom(s string) String

func StringFromPtr

func StringFromPtr(s *string) String

func (String) EncodeValues

func (m String) EncodeValues(key string, v *url.Values) error

func (*String) GobDecode

func (m *String) GobDecode(data []byte) error

func (String) GobEncode

func (m String) GobEncode() ([]byte, error)

func (String) MarshalJSON

func (m String) MarshalJSON() ([]byte, error)

func (String) NullValue

func (m String) NullValue() null.String

func (*String) UnmarshalJSON

func (m *String) UnmarshalJSON(data []byte) error

func (*String) UnmarshalText

func (m *String) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (String) ValueOrZero

func (m String) ValueOrZero() string

type Time

type Time null.Time

func NewTime

func NewTime(t time.Time, valid bool) Time

func TimeFrom

func TimeFrom(t time.Time) Time

func TimeFromPtr

func TimeFromPtr(t *time.Time) Time

func (Time) EncodeValues

func (t Time) EncodeValues(key string, v *url.Values) error

func (*Time) GobDecode

func (t *Time) GobDecode(data []byte) error

func (Time) GobEncode

func (t Time) GobEncode() ([]byte, error)

func (Time) MarshalJSON

func (t Time) MarshalJSON() ([]byte, error)

func (Time) NullValue

func (t Time) NullValue() null.Time

func (*Time) UnmarshalJSON

func (t *Time) UnmarshalJSON(data []byte) error

func (*Time) UnmarshalText

func (t *Time) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

func (Time) ValueOrZero

func (t Time) ValueOrZero() time.Time

Jump to

Keyboard shortcuts

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