├── .github └── workflows │ └── go.yml ├── LICENSE ├── README.md ├── generic.go ├── generic_test.go ├── go.mod ├── pointer.go ├── pointer_or_nil.go ├── pointer_test.go └── value.go /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Go 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | schedule: 9 | - cron: '42 3 * * 4' 10 | 11 | jobs: 12 | test: 13 | name: Test 14 | runs-on: ubuntu-20.04 15 | 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v2 19 | 20 | - name: Install Go tip 21 | run: | 22 | sudo rm -fr /opt/hostedtoolcache/go /usr/local/go /usr/bin/go /bin/go 23 | curl -o go.tar.gz -L \ 24 | https://github.com/AlekSi/golang-tip/releases/download/tip/master.linux-amd64.tar.gz 25 | sudo tar -C /usr/local -xzf go.tar.gz 26 | sudo ln -s /usr/local/go/bin/* /usr/local/bin/ 27 | go version 28 | rm go.tar.gz 29 | 30 | - name: Run tests 31 | run: go test -v 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Alexey Palazhchenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pointer 2 | 3 | [![Go Reference](https://pkg.go.dev/badge/github.com/AlekSi/pointer.svg)](https://pkg.go.dev/github.com/AlekSi/pointer) 4 | 5 | Go package `pointer` provides helpers to convert between pointers and values of built-in 6 | (and, with Go 1.18+ generics, of any) types. 7 | 8 | ``` 9 | go get github.com/AlekSi/pointer 10 | ``` 11 | 12 | API is stable. [Documentation](https://pkg.go.dev/github.com/AlekSi/pointer). 13 | 14 | ```go 15 | package motivationalexample 16 | 17 | import ( 18 | "encoding/json" 19 | 20 | "github.com/AlekSi/pointer" 21 | ) 22 | 23 | const ( 24 | defaultName = "some name" 25 | ) 26 | 27 | // Stuff contains optional fields. 28 | type Stuff struct { 29 | Name *string 30 | Comment *string 31 | Value *int64 32 | Time *time.Time 33 | } 34 | 35 | // SomeStuff makes some JSON-encoded stuff. 36 | func SomeStuff() (data []byte, err error) { 37 | return json.Marshal(&Stuff{ 38 | Name: pointer.ToString(defaultName), // can't say &defaultName 39 | Comment: pointer.ToString("not yet"), // can't say &"not yet" 40 | Value: pointer.ToInt64(42), // can't say &42 or &int64(42) 41 | Time: pointer.ToTime(time.Date(2014, 6, 25, 12, 24, 40, 0, time.UTC)), // can't say &time.Date(…) 42 | }) 43 | } 44 | ``` 45 | -------------------------------------------------------------------------------- /generic.go: -------------------------------------------------------------------------------- 1 | //go:build go1.18 2 | // +build go1.18 3 | 4 | package pointer 5 | 6 | // To returns a pointer to the passed value. 7 | func To[T any](t T) *T { 8 | return &t 9 | } 10 | 11 | // ToOrNil returns a pointer to the passed value, or nil, if the passed value is a zero value. 12 | // If the passed value has `IsZero() bool` method (for example, time.Time instance), 13 | // it is used to determine if the value is zero. 14 | func ToOrNil[T comparable](t T) *T { 15 | if z, ok := any(t).(interface{ IsZero() bool }); ok { 16 | if z.IsZero() { 17 | return nil 18 | } 19 | return &t 20 | } 21 | 22 | var zero T 23 | if t == zero { 24 | return nil 25 | } 26 | return &t 27 | } 28 | 29 | // Get returns the value from the passed pointer or the zero value if the pointer is nil. 30 | func Get[T any](t *T) T { 31 | if t == nil { 32 | var zero T 33 | return zero 34 | } 35 | return *t 36 | } 37 | -------------------------------------------------------------------------------- /generic_test.go: -------------------------------------------------------------------------------- 1 | //go:build go1.18 2 | // +build go1.18 3 | 4 | package pointer 5 | 6 | import ( 7 | "testing" 8 | "time" 9 | ) 10 | 11 | func TestGeneric(t *testing.T) { 12 | var x time.Time 13 | if *To(x) != x { 14 | t.Errorf("*To(%v)", x) 15 | } 16 | if ToOrNil(x) != nil { 17 | t.Errorf("ToOrNil(%v)", x) 18 | } 19 | if Get((*time.Time)(nil)) != x { 20 | t.Errorf("Time(%v)", nil) 21 | } 22 | 23 | x = time.Date(2014, 6, 25, 12, 24, 40, 0, time.UTC) 24 | if *To(x) != x { 25 | t.Errorf("*To(%v)", x) 26 | } 27 | if *ToOrNil(x) != x { 28 | t.Errorf("*ToOrNil(%v)", x) 29 | } 30 | if Get(&x) != x { 31 | t.Errorf("Get(%v)", &x) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/AlekSi/pointer 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /pointer.go: -------------------------------------------------------------------------------- 1 | // Package pointer provides helpers to convert between pointers and values of built-in (and, with generics, of any) types. 2 | package pointer // import "github.com/AlekSi/pointer" 3 | 4 | import ( 5 | "time" 6 | ) 7 | 8 | /* 9 | Order as in spec: 10 | bool byte complex64 complex128 error float32 float64 11 | int int8 int16 int32 int64 rune string 12 | uint uint8 uint16 uint32 uint64 uintptr 13 | time.Duration time.Time 14 | */ 15 | 16 | // ToBool returns a pointer to the passed bool value. 17 | func ToBool(b bool) *bool { 18 | return &b 19 | } 20 | 21 | // ToByte returns a pointer to the passed byte value. 22 | func ToByte(b byte) *byte { 23 | return &b 24 | } 25 | 26 | // ToComplex64 returns a pointer to the passed complex64 value. 27 | func ToComplex64(c complex64) *complex64 { 28 | return &c 29 | } 30 | 31 | // ToComplex128 returns a pointer to the passed complex128 value. 32 | func ToComplex128(c complex128) *complex128 { 33 | return &c 34 | } 35 | 36 | // ToError returns a pointer to the passed error value. 37 | func ToError(e error) *error { 38 | return &e 39 | } 40 | 41 | // ToFloat32 returns a pointer to the passed float32 value. 42 | func ToFloat32(f float32) *float32 { 43 | return &f 44 | } 45 | 46 | // ToFloat64 returns a pointer to the passed float64 value. 47 | func ToFloat64(f float64) *float64 { 48 | return &f 49 | } 50 | 51 | // ToInt returns a pointer to the passed int value. 52 | func ToInt(i int) *int { 53 | return &i 54 | } 55 | 56 | // ToInt8 returns a pointer to the passed int8 value. 57 | func ToInt8(i int8) *int8 { 58 | return &i 59 | } 60 | 61 | // ToInt16 returns a pointer to the passed int16 value. 62 | func ToInt16(i int16) *int16 { 63 | return &i 64 | } 65 | 66 | // ToInt32 returns a pointer to the passed int32 value. 67 | func ToInt32(i int32) *int32 { 68 | return &i 69 | } 70 | 71 | // ToInt64 returns a pointer to the passed int64 value. 72 | func ToInt64(i int64) *int64 { 73 | return &i 74 | } 75 | 76 | // ToRune returns a pointer to the passed rune value. 77 | func ToRune(r rune) *rune { 78 | return &r 79 | } 80 | 81 | // ToString returns a pointer to the passed string value. 82 | func ToString(s string) *string { 83 | return &s 84 | } 85 | 86 | // ToUint returns a pointer to the passed uint value. 87 | func ToUint(u uint) *uint { 88 | return &u 89 | } 90 | 91 | // ToUint8 returns a pointer to the passed uint8 value. 92 | func ToUint8(u uint8) *uint8 { 93 | return &u 94 | } 95 | 96 | // ToUint16 returns a pointer to the passed uint16 value. 97 | func ToUint16(u uint16) *uint16 { 98 | return &u 99 | } 100 | 101 | // ToUint32 returns a pointer to the passed uint32 value. 102 | func ToUint32(u uint32) *uint32 { 103 | return &u 104 | } 105 | 106 | // ToUint64 returns a pointer to the passed uint64 value. 107 | func ToUint64(u uint64) *uint64 { 108 | return &u 109 | } 110 | 111 | // ToUintptr returns a pointer to the passed uintptr value. 112 | func ToUintptr(u uintptr) *uintptr { 113 | return &u 114 | } 115 | 116 | // ToDuration returns a pointer to the passed time.Duration value. 117 | func ToDuration(d time.Duration) *time.Duration { 118 | return &d 119 | } 120 | 121 | // ToTime returns a pointer to the passed time.Time value. 122 | func ToTime(t time.Time) *time.Time { 123 | return &t 124 | } 125 | -------------------------------------------------------------------------------- /pointer_or_nil.go: -------------------------------------------------------------------------------- 1 | package pointer 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | /* 8 | Order as in spec: 9 | bool byte complex64 complex128 error float32 float64 10 | int int8 int16 int32 int64 rune string 11 | uint uint8 uint16 uint32 uint64 uintptr 12 | time.Duration time.Time 13 | */ 14 | 15 | // ToBoolOrNil returns a pointer to the passed bool value, or nil, if passed value is a zero value. 16 | func ToBoolOrNil(b bool) *bool { 17 | if b == false { 18 | return nil 19 | } 20 | return &b 21 | } 22 | 23 | // ToByteOrNil returns a pointer to the passed byte value, or nil, if passed value is a zero value. 24 | func ToByteOrNil(b byte) *byte { 25 | if b == 0 { 26 | return nil 27 | } 28 | return &b 29 | } 30 | 31 | // ToComplex64OrNil returns a pointer to the passed complex64 value, or nil, if passed value is a zero value. 32 | func ToComplex64OrNil(c complex64) *complex64 { 33 | if c == 0 { 34 | return nil 35 | } 36 | return &c 37 | } 38 | 39 | // ToComplex128OrNil returns a pointer to the passed complex128 value, or nil, if passed value is a zero value. 40 | func ToComplex128OrNil(c complex128) *complex128 { 41 | if c == 0 { 42 | return nil 43 | } 44 | return &c 45 | } 46 | 47 | // ToErrorOrNil returns a pointer to the passed error value, or nil, if passed value is a zero value. 48 | func ToErrorOrNil(e error) *error { 49 | if e == nil { 50 | return nil 51 | } 52 | return &e 53 | } 54 | 55 | // ToFloat32OrNil returns a pointer to the passed float32 value, or nil, if passed value is a zero value. 56 | func ToFloat32OrNil(f float32) *float32 { 57 | if f == 0 { 58 | return nil 59 | } 60 | return &f 61 | } 62 | 63 | // ToFloat64OrNil returns a pointer to the passed float64 value, or nil, if passed value is a zero value. 64 | func ToFloat64OrNil(f float64) *float64 { 65 | if f == 0 { 66 | return nil 67 | } 68 | return &f 69 | } 70 | 71 | // ToIntOrNil returns a pointer to the passed int value, or nil, if passed value is a zero value. 72 | func ToIntOrNil(i int) *int { 73 | if i == 0 { 74 | return nil 75 | } 76 | return &i 77 | } 78 | 79 | // ToInt8OrNil returns a pointer to the passed int8 value, or nil, if passed value is a zero value. 80 | func ToInt8OrNil(i int8) *int8 { 81 | if i == 0 { 82 | return nil 83 | } 84 | return &i 85 | } 86 | 87 | // ToInt16OrNil returns a pointer to the passed int16 value, or nil, if passed value is a zero value. 88 | func ToInt16OrNil(i int16) *int16 { 89 | if i == 0 { 90 | return nil 91 | } 92 | return &i 93 | } 94 | 95 | // ToInt32OrNil returns a pointer to the passed int32 value, or nil, if passed value is a zero value. 96 | func ToInt32OrNil(i int32) *int32 { 97 | if i == 0 { 98 | return nil 99 | } 100 | return &i 101 | } 102 | 103 | // ToInt64OrNil returns a pointer to the passed int64 value, or nil, if passed value is a zero value. 104 | func ToInt64OrNil(i int64) *int64 { 105 | if i == 0 { 106 | return nil 107 | } 108 | return &i 109 | } 110 | 111 | // ToRuneOrNil returns a pointer to the passed rune value, or nil, if passed value is a zero value. 112 | func ToRuneOrNil(r rune) *rune { 113 | if r == 0 { 114 | return nil 115 | } 116 | return &r 117 | } 118 | 119 | // ToStringOrNil returns a pointer to the passed string value, or nil, if passed value is a zero value. 120 | func ToStringOrNil(s string) *string { 121 | if s == "" { 122 | return nil 123 | } 124 | return &s 125 | } 126 | 127 | // ToUintOrNil returns a pointer to the passed uint value, or nil, if passed value is a zero value. 128 | func ToUintOrNil(u uint) *uint { 129 | if u == 0 { 130 | return nil 131 | } 132 | return &u 133 | } 134 | 135 | // ToUint8OrNil returns a pointer to the passed uint8 value, or nil, if passed value is a zero value. 136 | func ToUint8OrNil(u uint8) *uint8 { 137 | if u == 0 { 138 | return nil 139 | } 140 | return &u 141 | } 142 | 143 | // ToUint16OrNil returns a pointer to the passed uint16 value, or nil, if passed value is a zero value. 144 | func ToUint16OrNil(u uint16) *uint16 { 145 | if u == 0 { 146 | return nil 147 | } 148 | return &u 149 | } 150 | 151 | // ToUint32OrNil returns a pointer to the passed uint32 value, or nil, if passed value is a zero value. 152 | func ToUint32OrNil(u uint32) *uint32 { 153 | if u == 0 { 154 | return nil 155 | } 156 | return &u 157 | } 158 | 159 | // ToUint64OrNil returns a pointer to the passed uint64 value, or nil, if passed value is a zero value. 160 | func ToUint64OrNil(u uint64) *uint64 { 161 | if u == 0 { 162 | return nil 163 | } 164 | return &u 165 | } 166 | 167 | // ToUintptrOrNil returns a pointer to the passed uintptr value, or nil, if passed value is a zero value. 168 | func ToUintptrOrNil(u uintptr) *uintptr { 169 | if u == 0 { 170 | return nil 171 | } 172 | return &u 173 | } 174 | 175 | // ToDurationOrNil returns a pointer to the passed time.Duration value, or nil, if passed value is a zero value. 176 | func ToDurationOrNil(d time.Duration) *time.Duration { 177 | if d == 0 { 178 | return nil 179 | } 180 | return &d 181 | } 182 | 183 | // ToTimeOrNil returns a pointer to the passed time.Time value, or nil, if passed value is a zero value (t.IsZero() returns true). 184 | func ToTimeOrNil(t time.Time) *time.Time { 185 | if t.IsZero() { 186 | return nil 187 | } 188 | return &t 189 | } 190 | -------------------------------------------------------------------------------- /pointer_test.go: -------------------------------------------------------------------------------- 1 | package pointer 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "fmt" 7 | "testing" 8 | "time" 9 | ) 10 | 11 | /* 12 | Order as in spec: 13 | bool byte complex64 complex128 error float32 float64 14 | int int8 int16 int32 int64 rune string 15 | uint uint8 uint16 uint32 uint64 uintptr 16 | time.Duration time.Time 17 | */ 18 | 19 | func TestBool(t *testing.T) { 20 | var x bool 21 | if *ToBool(x) != x { 22 | t.Errorf("*ToBool(%v)", x) 23 | } 24 | if ToBoolOrNil(x) != nil { 25 | t.Errorf("ToBoolOrNil(%v)", x) 26 | } 27 | if GetBool(nil) != x { 28 | t.Errorf("GetBool(%v)", nil) 29 | } 30 | 31 | x = true 32 | if *ToBool(x) != x { 33 | t.Errorf("*ToBool(%v)", x) 34 | } 35 | if *ToBoolOrNil(x) != x { 36 | t.Errorf("*ToBoolOrNil(%v)", x) 37 | } 38 | if GetBool(&x) != x { 39 | t.Errorf("GetBool(%v)", &x) 40 | } 41 | } 42 | 43 | func TestByte(t *testing.T) { 44 | var x byte 45 | if *ToByte(x) != x { 46 | t.Errorf("*ToByte(%v)", x) 47 | } 48 | if ToByteOrNil(x) != nil { 49 | t.Errorf("ToByteOrNil(%v)", x) 50 | } 51 | if GetByte(nil) != x { 52 | t.Errorf("GetByte(%v)", nil) 53 | } 54 | 55 | x = 42 56 | if *ToByte(x) != x { 57 | t.Errorf("*ToByte(%v)", x) 58 | } 59 | if *ToByteOrNil(x) != x { 60 | t.Errorf("*ToByteOrNil(%v)", x) 61 | } 62 | if GetByte(&x) != x { 63 | t.Errorf("GetByte(%v)", &x) 64 | } 65 | } 66 | 67 | func TestComplex64(t *testing.T) { 68 | var x complex64 69 | if *ToComplex64(x) != x { 70 | t.Errorf("*ToComplex64(%v)", x) 71 | } 72 | if ToComplex64OrNil(x) != nil { 73 | t.Errorf("ToComplex64OrNil(%v)", x) 74 | } 75 | if GetComplex64(nil) != x { 76 | t.Errorf("GetComplex64(%v)", nil) 77 | } 78 | 79 | x = 42 80 | if *ToComplex64(x) != x { 81 | t.Errorf("*ToComplex64(%v)", x) 82 | } 83 | if *ToComplex64OrNil(x) != x { 84 | t.Errorf("*ToComplex64OrNil(%v)", x) 85 | } 86 | if GetComplex64(&x) != x { 87 | t.Errorf("GetComplex64(%v)", &x) 88 | } 89 | } 90 | 91 | func TestComplex128(t *testing.T) { 92 | var x complex128 93 | if *ToComplex128(x) != x { 94 | t.Errorf("*ToComplex128(%v)", x) 95 | } 96 | if ToComplex128OrNil(x) != nil { 97 | t.Errorf("ToComplex128OrNil(%v)", x) 98 | } 99 | if GetComplex128(nil) != x { 100 | t.Errorf("GetComplex128(%v)", nil) 101 | } 102 | 103 | x = 42 104 | if *ToComplex128(x) != x { 105 | t.Errorf("*ToComplex128(%v)", x) 106 | } 107 | if *ToComplex128OrNil(x) != x { 108 | t.Errorf("*ToComplex128OrNil(%v)", x) 109 | } 110 | if GetComplex128(&x) != x { 111 | t.Errorf("GetComplex128(%v)", &x) 112 | } 113 | } 114 | 115 | func TestError(t *testing.T) { 116 | var x error 117 | if *ToError(x) != x { 118 | t.Errorf("*ToError(%v)", x) 119 | } 120 | if ToErrorOrNil(x) != nil { 121 | t.Errorf("ToErrorOrNil(%v)", x) 122 | } 123 | if GetError(nil) != x { 124 | t.Errorf("GetError(%v)", nil) 125 | } 126 | 127 | x = errors.New("error") 128 | if *ToError(x) != x { 129 | t.Errorf("*ToError(%v)", x) 130 | } 131 | if *ToErrorOrNil(x) != x { 132 | t.Errorf("*ToErrorOrNil(%v)", x) 133 | } 134 | if GetError(&x) != x { 135 | t.Errorf("GetError(%v)", &x) 136 | } 137 | } 138 | 139 | func TestFloat32(t *testing.T) { 140 | var x float32 141 | if *ToFloat32(x) != x { 142 | t.Errorf("*ToFloat32(%v)", x) 143 | } 144 | if ToFloat32OrNil(x) != nil { 145 | t.Errorf("ToFloat32OrNil(%v)", x) 146 | } 147 | if GetFloat32(nil) != x { 148 | t.Errorf("GetFloat32(%v)", nil) 149 | } 150 | 151 | x = 42 152 | if *ToFloat32(x) != x { 153 | t.Errorf("*ToFloat32(%v)", x) 154 | } 155 | if *ToFloat32OrNil(x) != x { 156 | t.Errorf("*ToFloat32OrNil(%v)", x) 157 | } 158 | if GetFloat32(&x) != x { 159 | t.Errorf("GetFloat32(%v)", &x) 160 | } 161 | } 162 | 163 | func TestFloat64(t *testing.T) { 164 | var x float64 165 | if *ToFloat64(x) != x { 166 | t.Errorf("*ToFloat64(%v)", x) 167 | } 168 | if ToFloat64OrNil(x) != nil { 169 | t.Errorf("ToFloat64OrNil(%v)", x) 170 | } 171 | if GetFloat64(nil) != x { 172 | t.Errorf("GetFloat64(%v)", nil) 173 | } 174 | 175 | x = 42 176 | if *ToFloat64(x) != x { 177 | t.Errorf("*ToFloat64(%v)", x) 178 | } 179 | if *ToFloat64OrNil(x) != x { 180 | t.Errorf("*ToFloat64OrNil(%v)", x) 181 | } 182 | if GetFloat64(&x) != x { 183 | t.Errorf("GetFloat64(%v)", &x) 184 | } 185 | } 186 | 187 | func TestInt(t *testing.T) { 188 | var x int 189 | if *ToInt(x) != x { 190 | t.Errorf("*ToInt(%v)", x) 191 | } 192 | if ToIntOrNil(x) != nil { 193 | t.Errorf("ToIntOrNil(%v)", x) 194 | } 195 | if GetInt(nil) != x { 196 | t.Errorf("GetInt(%v)", nil) 197 | } 198 | 199 | x = 42 200 | if *ToInt(x) != x { 201 | t.Errorf("*ToInt(%v)", x) 202 | } 203 | if *ToIntOrNil(x) != x { 204 | t.Errorf("*ToIntOrNil(%v)", x) 205 | } 206 | if GetInt(&x) != x { 207 | t.Errorf("GetInt(%v)", &x) 208 | } 209 | } 210 | 211 | func TestInt8(t *testing.T) { 212 | var x int8 213 | if *ToInt8(x) != x { 214 | t.Errorf("*ToInt8(%v)", x) 215 | } 216 | if ToInt8OrNil(x) != nil { 217 | t.Errorf("ToInt8OrNil(%v)", x) 218 | } 219 | if GetInt8(nil) != x { 220 | t.Errorf("GetInt8(%v)", nil) 221 | } 222 | 223 | x = 42 224 | if *ToInt8(x) != x { 225 | t.Errorf("*ToInt8(%v)", x) 226 | } 227 | if *ToInt8OrNil(x) != x { 228 | t.Errorf("*ToInt8OrNil(%v)", x) 229 | } 230 | if GetInt8(&x) != x { 231 | t.Errorf("GetInt8(%v)", &x) 232 | } 233 | } 234 | 235 | func TestInt16(t *testing.T) { 236 | var x int16 237 | if *ToInt16(x) != x { 238 | t.Errorf("*ToInt16(%v)", x) 239 | } 240 | if ToInt16OrNil(x) != nil { 241 | t.Errorf("ToInt16OrNil(%v)", x) 242 | } 243 | if GetInt16(nil) != x { 244 | t.Errorf("GetInt16(%v)", nil) 245 | } 246 | 247 | x = 42 248 | if *ToInt16(x) != x { 249 | t.Errorf("*ToInt16(%v)", x) 250 | } 251 | if *ToInt16OrNil(x) != x { 252 | t.Errorf("*ToInt16OrNil(%v)", x) 253 | } 254 | if GetInt16(&x) != x { 255 | t.Errorf("GetInt16(%v)", &x) 256 | } 257 | } 258 | 259 | func TestInt32(t *testing.T) { 260 | var x int32 261 | if *ToInt32(x) != x { 262 | t.Errorf("*ToInt32(%v)", x) 263 | } 264 | if ToInt32OrNil(x) != nil { 265 | t.Errorf("ToInt32OrNil(%v)", x) 266 | } 267 | if GetInt32(nil) != x { 268 | t.Errorf("GetInt32(%v)", nil) 269 | } 270 | 271 | x = 42 272 | if *ToInt32(x) != x { 273 | t.Errorf("*ToInt32(%v)", x) 274 | } 275 | if *ToInt32OrNil(x) != x { 276 | t.Errorf("*ToInt32OrNil(%v)", x) 277 | } 278 | if GetInt32(&x) != x { 279 | t.Errorf("GetInt32(%v)", &x) 280 | } 281 | } 282 | 283 | func TestInt64(t *testing.T) { 284 | var x int64 285 | if *ToInt64(x) != x { 286 | t.Errorf("*ToInt64(%v)", x) 287 | } 288 | if ToInt64OrNil(x) != nil { 289 | t.Errorf("ToInt64OrNil(%v)", x) 290 | } 291 | if GetInt64(nil) != x { 292 | t.Errorf("GetInt64(%v)", nil) 293 | } 294 | 295 | x = 42 296 | if *ToInt64(x) != x { 297 | t.Errorf("*ToInt64(%v)", x) 298 | } 299 | if *ToInt64OrNil(x) != x { 300 | t.Errorf("*ToInt64OrNil(%v)", x) 301 | } 302 | if GetInt64(&x) != x { 303 | t.Errorf("GetInt64(%v)", &x) 304 | } 305 | } 306 | 307 | func TestRune(t *testing.T) { 308 | var x rune 309 | if *ToRune(x) != x { 310 | t.Errorf("*ToRune(%v)", x) 311 | } 312 | if ToRuneOrNil(x) != nil { 313 | t.Errorf("ToRuneOrNil(%v)", x) 314 | } 315 | if GetRune(nil) != x { 316 | t.Errorf("GetRune(%v)", nil) 317 | } 318 | 319 | x = 'x' 320 | if *ToRune(x) != x { 321 | t.Errorf("*ToRune(%v)", x) 322 | } 323 | if *ToRuneOrNil(x) != x { 324 | t.Errorf("*ToRuneOrNil(%v)", x) 325 | } 326 | if GetRune(&x) != x { 327 | t.Errorf("GetRune(%v)", &x) 328 | } 329 | } 330 | 331 | func TestString(t *testing.T) { 332 | var x string 333 | if *ToString(x) != x { 334 | t.Errorf("*ToString(%v)", x) 335 | } 336 | if ToStringOrNil(x) != nil { 337 | t.Errorf("ToStringOrNil(%v)", x) 338 | } 339 | if GetString(nil) != x { 340 | t.Errorf("GetString(%v)", nil) 341 | } 342 | 343 | x = "x" 344 | if *ToString(x) != x { 345 | t.Errorf("*ToString(%v)", x) 346 | } 347 | if *ToStringOrNil(x) != x { 348 | t.Errorf("*ToStringOrNil(%v)", x) 349 | } 350 | if GetString(&x) != x { 351 | t.Errorf("GetString(%v)", &x) 352 | } 353 | } 354 | 355 | func TestUint(t *testing.T) { 356 | var x uint 357 | if *ToUint(x) != x { 358 | t.Errorf("*ToUint(%v)", x) 359 | } 360 | if ToUintOrNil(x) != nil { 361 | t.Errorf("ToUintOrNil(%v)", x) 362 | } 363 | if GetUint(nil) != x { 364 | t.Errorf("GetUint(%v)", nil) 365 | } 366 | 367 | x = 42 368 | if *ToUint(x) != x { 369 | t.Errorf("*ToUint(%v)", x) 370 | } 371 | if *ToUintOrNil(x) != x { 372 | t.Errorf("*ToUintOrNil(%v)", x) 373 | } 374 | if GetUint(&x) != x { 375 | t.Errorf("GetUint(%v)", &x) 376 | } 377 | } 378 | 379 | func TestUint8(t *testing.T) { 380 | var x uint8 381 | if *ToUint8(x) != x { 382 | t.Errorf("*ToUint8(%v)", x) 383 | } 384 | if ToUint8OrNil(x) != nil { 385 | t.Errorf("ToUint8OrNil(%v)", x) 386 | } 387 | if GetUint8(nil) != x { 388 | t.Errorf("GetUint8(%v)", nil) 389 | } 390 | 391 | x = 42 392 | if *ToUint8(x) != x { 393 | t.Errorf("*ToUint8(%v)", x) 394 | } 395 | if *ToUint8OrNil(x) != x { 396 | t.Errorf("*ToUint8OrNil(%v)", x) 397 | } 398 | if GetUint8(&x) != x { 399 | t.Errorf("GetUint8(%v)", &x) 400 | } 401 | } 402 | 403 | func TestUint16(t *testing.T) { 404 | var x uint16 405 | if *ToUint16(x) != x { 406 | t.Errorf("*ToUint16(%v)", x) 407 | } 408 | if ToUint16OrNil(x) != nil { 409 | t.Errorf("ToUint16OrNil(%v)", x) 410 | } 411 | if GetUint16(nil) != x { 412 | t.Errorf("GetUint16(%v)", nil) 413 | } 414 | 415 | x = 42 416 | if *ToUint16(x) != x { 417 | t.Errorf("*ToUint16(%v)", x) 418 | } 419 | if *ToUint16OrNil(x) != x { 420 | t.Errorf("*ToUint16OrNil(%v)", x) 421 | } 422 | if GetUint16(&x) != x { 423 | t.Errorf("GetUint16(%v)", &x) 424 | } 425 | } 426 | 427 | func TestUint32(t *testing.T) { 428 | var x uint32 429 | if *ToUint32(x) != x { 430 | t.Errorf("*ToUint32(%v)", x) 431 | } 432 | if ToUint32OrNil(x) != nil { 433 | t.Errorf("ToUint32OrNil(%v)", x) 434 | } 435 | if GetUint32(nil) != x { 436 | t.Errorf("GetUint32(%v)", nil) 437 | } 438 | 439 | x = 42 440 | if *ToUint32(x) != x { 441 | t.Errorf("*ToUint32(%v)", x) 442 | } 443 | if *ToUint32OrNil(x) != x { 444 | t.Errorf("*ToUint32OrNil(%v)", x) 445 | } 446 | if GetUint32(&x) != x { 447 | t.Errorf("GetUint32(%v)", &x) 448 | } 449 | } 450 | 451 | func TestUint64(t *testing.T) { 452 | var x uint64 453 | if *ToUint64(x) != x { 454 | t.Errorf("*ToUint64(%v)", x) 455 | } 456 | if ToUint64OrNil(x) != nil { 457 | t.Errorf("ToUint64OrNil(%v)", x) 458 | } 459 | if GetUint64(nil) != x { 460 | t.Errorf("GetUint64(%v)", nil) 461 | } 462 | 463 | x = 42 464 | if *ToUint64(x) != x { 465 | t.Errorf("*ToUint64(%v)", x) 466 | } 467 | if *ToUint64OrNil(x) != x { 468 | t.Errorf("*ToUint64OrNil(%v)", x) 469 | } 470 | if GetUint64(&x) != x { 471 | t.Errorf("GetUint64(%v)", &x) 472 | } 473 | } 474 | 475 | func TestUintptr(t *testing.T) { 476 | var x uintptr 477 | if *ToUintptr(x) != x { 478 | t.Errorf("*ToUintptr(%v)", x) 479 | } 480 | if ToUintptrOrNil(x) != nil { 481 | t.Errorf("ToUintptrOrNil(%v)", x) 482 | } 483 | if GetUintptr(nil) != x { 484 | t.Errorf("GetUintptr(%v)", nil) 485 | } 486 | 487 | x = 42 488 | if *ToUintptr(x) != x { 489 | t.Errorf("*ToUintptr(%v)", x) 490 | } 491 | if *ToUintptrOrNil(x) != x { 492 | t.Errorf("*ToUintptrOrNil(%v)", x) 493 | } 494 | if GetUintptr(&x) != x { 495 | t.Errorf("GetUintptr(%v)", &x) 496 | } 497 | } 498 | 499 | func TestDuration(t *testing.T) { 500 | var x time.Duration 501 | if *ToDuration(x) != x { 502 | t.Errorf("*ToDuration(%v)", x) 503 | } 504 | if ToDurationOrNil(x) != nil { 505 | t.Errorf("ToDurationOrNil(%v)", x) 506 | } 507 | if GetDuration(nil) != x { 508 | t.Errorf("GetDuration(%v)", nil) 509 | } 510 | 511 | x = time.Second 512 | if *ToDuration(x) != x { 513 | t.Errorf("*ToDuration(%v)", x) 514 | } 515 | if *ToDurationOrNil(x) != x { 516 | t.Errorf("*ToDurationOrNil(%v)", x) 517 | } 518 | if GetDuration(&x) != x { 519 | t.Errorf("GetDuration(%v)", &x) 520 | } 521 | } 522 | 523 | func TestTime(t *testing.T) { 524 | var x time.Time 525 | if *ToTime(x) != x { 526 | t.Errorf("*ToTime(%v)", x) 527 | } 528 | if ToTimeOrNil(x) != nil { 529 | t.Errorf("ToTimeOrNil(%v)", x) 530 | } 531 | if GetTime(nil) != x { 532 | t.Errorf("GetTime(%v)", nil) 533 | } 534 | 535 | x = time.Date(2014, 6, 25, 12, 24, 40, 0, time.UTC) 536 | if *ToTime(x) != x { 537 | t.Errorf("*ToTime(%v)", x) 538 | } 539 | if *ToTimeOrNil(x) != x { 540 | t.Errorf("*ToTimeOrNil(%v)", x) 541 | } 542 | if GetTime(&x) != x { 543 | t.Errorf("GetTime(%v)", &x) 544 | } 545 | } 546 | 547 | func Example() { 548 | const ( 549 | defaultName = "some name" 550 | ) 551 | 552 | // Stuff contains optional fields. 553 | type Stuff struct { 554 | Name *string 555 | Comment *string 556 | Value *int64 557 | Time *time.Time 558 | } 559 | 560 | b, _ := json.Marshal(&Stuff{ 561 | Name: ToString(defaultName), // can't say &defaultName 562 | Comment: ToString("not yet"), // can't say &"not yet" 563 | Value: ToInt64(42), // can't say &42 or &int64(42) 564 | Time: ToTime(time.Date(2014, 6, 25, 12, 24, 40, 0, time.UTC)), // can't say &time.Date(…) 565 | }) 566 | 567 | fmt.Printf("%s", b) 568 | 569 | // Output: {"Name":"some name","Comment":"not yet","Value":42,"Time":"2014-06-25T12:24:40Z"} 570 | } 571 | -------------------------------------------------------------------------------- /value.go: -------------------------------------------------------------------------------- 1 | package pointer 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | /* 8 | Order as in spec: 9 | bool byte complex64 complex128 error float32 float64 10 | int int8 int16 int32 int64 rune string 11 | uint uint8 uint16 uint32 uint64 uintptr 12 | time.Duration time.Time 13 | */ 14 | 15 | // GetBool returns the value of the bool pointer passed in or false if the pointer is nil. 16 | func GetBool(b *bool) bool { 17 | if b == nil { 18 | return false 19 | } 20 | return *b 21 | } 22 | 23 | // GetByte returns the value of the byte pointer passed in or 0 if the pointer is nil. 24 | func GetByte(b *byte) byte { 25 | if b == nil { 26 | return 0 27 | } 28 | return *b 29 | } 30 | 31 | // GetComplex64 returns the value of the complex64 pointer passed in or 0 if the pointer is nil. 32 | func GetComplex64(c *complex64) complex64 { 33 | if c == nil { 34 | return 0 35 | } 36 | return *c 37 | } 38 | 39 | // GetComplex128 returns the value of the complex128 pointer passed in or 0 if the pointer is nil. 40 | func GetComplex128(c *complex128) complex128 { 41 | if c == nil { 42 | return 0 43 | } 44 | return *c 45 | } 46 | 47 | // GetError returns the value of the error pointer passed in or nil if the pointer is nil. 48 | func GetError(e *error) error { 49 | if e == nil { 50 | return nil 51 | } 52 | return *e 53 | } 54 | 55 | // GetFloat32 returns the value of the float32 pointer passed in or 0 if the pointer is nil. 56 | func GetFloat32(f *float32) float32 { 57 | if f == nil { 58 | return 0 59 | } 60 | return *f 61 | } 62 | 63 | // GetFloat64 returns the value of the float64 pointer passed in or 0 if the pointer is nil. 64 | func GetFloat64(f *float64) float64 { 65 | if f == nil { 66 | return 0 67 | } 68 | return *f 69 | } 70 | 71 | // GetInt returns the value of the int pointer passed in or 0 if the pointer is nil. 72 | func GetInt(i *int) int { 73 | if i == nil { 74 | return 0 75 | } 76 | return *i 77 | } 78 | 79 | // GetInt8 returns the value of the int8 pointer passed in or 0 if the pointer is nil. 80 | func GetInt8(i *int8) int8 { 81 | if i == nil { 82 | return 0 83 | } 84 | return *i 85 | } 86 | 87 | // GetInt16 returns the value of the int16 pointer passed in or 0 if the pointer is nil. 88 | func GetInt16(i *int16) int16 { 89 | if i == nil { 90 | return 0 91 | } 92 | return *i 93 | } 94 | 95 | // GetInt32 returns the value of the int32 pointer passed in or 0 if the pointer is nil. 96 | func GetInt32(i *int32) int32 { 97 | if i == nil { 98 | return 0 99 | } 100 | return *i 101 | } 102 | 103 | // GetInt64 returns the value of the int64 pointer passed in or 0 if the pointer is nil. 104 | func GetInt64(i *int64) int64 { 105 | if i == nil { 106 | return 0 107 | } 108 | return *i 109 | } 110 | 111 | // GetRune returns the value of the rune pointer passed in or 0 if the pointer is nil. 112 | func GetRune(r *rune) rune { 113 | if r == nil { 114 | return 0 115 | } 116 | return *r 117 | } 118 | 119 | // GetString returns the value of the string pointer passed in or empty string if the pointer is nil. 120 | func GetString(s *string) string { 121 | if s == nil { 122 | return "" 123 | } 124 | return *s 125 | } 126 | 127 | // GetUint returns the value of the uint pointer passed in or 0 if the pointer is nil. 128 | func GetUint(u *uint) uint { 129 | if u == nil { 130 | return 0 131 | } 132 | return *u 133 | } 134 | 135 | // GetUint8 returns the value of the uint8 pointer passed in or 0 if the pointer is nil. 136 | func GetUint8(u *uint8) uint8 { 137 | if u == nil { 138 | return 0 139 | } 140 | return *u 141 | } 142 | 143 | // GetUint16 returns the value of the uint16 pointer passed in or 0 if the pointer is nil. 144 | func GetUint16(u *uint16) uint16 { 145 | if u == nil { 146 | return 0 147 | } 148 | return *u 149 | } 150 | 151 | // GetUint32 returns the value of the uint32 pointer passed in or 0 if the pointer is nil. 152 | func GetUint32(u *uint32) uint32 { 153 | if u == nil { 154 | return 0 155 | } 156 | return *u 157 | } 158 | 159 | // GetUint64 returns the value of the uint64 pointer passed in or 0 if the pointer is nil. 160 | func GetUint64(u *uint64) uint64 { 161 | if u == nil { 162 | return 0 163 | } 164 | return *u 165 | } 166 | 167 | // GetUintptr returns the value of the uintptr pointer passed in or 0 if the pointer is nil. 168 | func GetUintptr(u *uintptr) uintptr { 169 | if u == nil { 170 | return 0 171 | } 172 | return *u 173 | } 174 | 175 | // GetDuration returns the value of the duration pointer passed in or 0 if the pointer is nil. 176 | func GetDuration(d *time.Duration) time.Duration { 177 | if d == nil { 178 | return 0 179 | } 180 | return *d 181 | } 182 | 183 | // GetTime returns the value of the time pointer passed in or zero time.Time if the pointer is nil. 184 | func GetTime(t *time.Time) time.Time { 185 | if t == nil { 186 | return time.Time{} 187 | } 188 | return *t 189 | } 190 | --------------------------------------------------------------------------------