attrs_go

package module
v1.1.4 Latest Latest
Warning

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

Go to latest
Published: Nov 6, 2023 License: MIT Imports: 7 Imported by: 0

README

Attrs-go

Coverage Status build GoDoc

Overview

Tool for working with structure fields:

  • analog of Python 'getattr' and 'setattr'
  • some useful funcs to changing and rounding struct fields

Content

Installation

To install the package run

go get -u github.com/ruauka/attrs-go

Usage

GetAttr

Get struct field value.

package main

import (
    "fmt"
    
    attrs "github.com/ruauka/attrs-go"
)

type User struct {
    Username string
}

func main() {
    user := User{Username: "username value"}
    
    value, _ := attrs.GetAttr(user, "Username")
    fmt.Println(value) // username value
}
SetAttr

Set new value at structure field.

package main

import (
    "fmt"
    
    attrs "github.com/ruauka/attrs-go"
)

type User struct {
    Username string
}

func main() {
    u := &User{Username: "username value"}
    
    if err := attrs.SetAttr(u, "new username value", "Username"); err != nil {
      fmt.Println(err)
    }
    
    fmt.Println(u.Username) // new username value
}
Round

Float64 and Float32 rounder to certain precision.

package main

import (
    "fmt"
    "reflect"
    
    attrs "github.com/ruauka/attrs-go"
)

var (
    val32 float32 = 0.12345
    val64 float64 = 0.12345
)

func main() {
    res32 := attrs.Round(val32, 3)
    fmt.Println(res32)                 // 0.123
    fmt.Println(reflect.TypeOf(res32)) // float32
  
    res64 := attrs.Round(val64, 3)
    fmt.Println(res64)                 // 0.123
    fmt.Println(reflect.TypeOf(res64)) // float64
}
SetStructAttrs

Update current structure fields with the values of the new structure fields.

package main

import (
    "fmt"
    
    attrs "github.com/ruauka/attrs-go"
)

type User struct {
    Username string // will change by pte
    Age      int    // will change by value
    Married  bool   // will be the same
}

type NewUser struct {
    Username *string `json:"username"`
    Age      int     `json:"age"`
    Married  *bool   `json:"married"` // nil
}

func main() {
    user := &User{
        Username: "username",
        Age:      30,
        Married:  true,
    }
    
    newUserName := "new_username"
    
    newUser := NewUser{
        Username: &newUserName,
        Age:      35,
        Married:  nil,
    }
    
    fmt.Printf("%s, %d, %v\n", user.Username, user.Age, user.Married) // username, 30, true
    
    if err := attrs.SetStructAttrs(user, newUser); err != nil {
        fmt.Println(err)
    }
    
    fmt.Printf("%s, %d, %v\n", user.Username, user.Age, user.Married) // new_username, 35, true
}
RoundFloatStruct

Round up float struct fields to certain precision.

package main

import (
    "fmt"
    
    attrs "github.com/ruauka/attrs-go"
)

type Foo struct {
    Field1 float32
    Field2 float64
    Field3 []float32
    Field4 []float64
    Field5 [3]float32
    Field6 [3]float64
    Field7 int    // will be the same
    Field8 string // will be the same
}

func main() {
    foo := &Foo{
        Field1: 1.1111,
        Field2: 2.2222,
        Field3: []float32{1.1111, 2.2222, 3.3333},
        Field4: []float64{4.4444, 5.5555, 7.7777},
        Field5: [3]float32{1.1111, 2.2222, 3.3333},
        Field6: [3]float64{4.4444, 5.5555, 7.7777},
        Field7: 7,
        Field8: "field8",
    }

    fmt.Printf("%+v\n", *foo)
    // {
    //Field1:1.1111 Field2:2.2222
    //Field3:[1.1111 2.2222 3.3333] Field4:[4.4444 5.5555 7.7777]
    //Field5:[1.1111 2.2222 3.3333] Field6:[4.4444 5.5555 7.7777]
    //Field7:7 Field8:field8
    //}
    
    if err := attrs.RoundFloatStruct(foo, 3); err != nil {
        fmt.Println(err)
    }
    
    fmt.Printf("%+v", *foo)
    // {
    //Field1:1.112 Field2:2.223
    //Field3:[1.112 2.223 3.334] Field4:[4.445 5.556 7.778]
    //Field5:[1.112 2.223 3.334] Field6:[4.445 5.556 7.778]
    //Field7:7 Field8:field8
    //}
}
Intersection

Find intersection of two arrays. Returns new slice.

package main

import (
    "fmt"
    
    attrs "github.com/ruauka/attrs-go"
)

var (
    intsL = []int{1, 2, 3}
    intsR = []int{1, 2, 4}
    
    floatsL = []float64{1.1, 2.2, 3.3}
    floatsR = []float64{1.1, 2.2, 4.4}
    
    strL = []string{"aaa", "bbb", "ccc"}
    strR = []string{"aaa", "bbb", "ddd"}
)

func main() {
    resInts, _ := attrs.Intersection(intsL, intsR)
    fmt.Println(resInts) // [1 2]
    
    resFloats, _ := attrs.Intersection(floatsL, floatsR)
    fmt.Println(resFloats) // [1.1 2.2]
    
    resStrs, _ := attrs.Intersection(strL, strR)
    fmt.Println(resStrs) // [aaa bbb]
}
SlicesConcat

Concatenation of multiple slices.

package main

import (
    "fmt"
  
    attrs "github.com/ruauka/attrs-go"
)

func main() {
    var (
        ints1 = []int{1, 2, 3}
        ints2 = []int{4, 5, 6}
        ints3 = []int{7, 8, 9}
    
        strs1 = []string{"1", "2", "3"}
        strs2 = []string{"4", "5", "6"}
        strs3 = []string{"7", "8", "9"}
    )
    
    ints := attrs.SlicesConcat(ints1, ints2, ints3)
    fmt.Println(ints) // [1 2 3 4 5 6 7 8 9]
    
    strs := attrs.SlicesConcat(strs1, strs2, strs3)
    fmt.Println(strs) // [1 2 3 4 5 6 7 8 9]
}
TimeDelta

The difference between the two dates for each value

package main

import (
    "fmt"
    "time"
    
    attrs "github.com/ruauka/attrs-go"
)

func main() {
    var (
        from = time.Date(2022, 5, 25, 1, 1, 1, 1, time.UTC)
        to   = time.Date(2023, 5, 25, 1, 1, 1, 1, time.UTC)
    )
    
    res := attrs.Elapsed(from, to)
    fmt.Println(res)           // &{1 0 0 0 0 0 0 12 365 8760 525600 31536000}
    fmt.Println(res.TotalDays) // 365
}

Documentation

Overview

Package attrs_go - tool for working with structure fields. Analog of Python 'getattr' and 'setattr', also some useful funcs to change and rounding struct fields.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrNotStruct           = errors.New("not a struct")
	ErrFieldNotInStruct    = errors.New("field not in struct")
	ErrUnexportedField     = errors.New("field not exported")
	ErrWrongFieldValueType = errors.New("wrong field value type")
	ErrNotPointerStruct    = errors.New("struct passed not by pointer")
	ErrPointerStruct       = errors.New("struct passed by pointer")
	ErrLenSlices           = errors.New("slices must be the same length")
)

lib errors.

Functions

func GetAttr

func GetAttr(obj interface{}, fieldName string) (interface{}, error)

GetAttr - get struct field value. 'obj': value param, fields can be ptr or value. 'fieldName': value param.

Example
type User struct {
	Username string
}

user := User{Username: "username"}

value, err := GetAttr(user, "Username")
if err != nil {
	log.Fatal(err)
}

fmt.Println(value)
Output:

username

func Intersection added in v1.1.4

func Intersection[T cmp.Ordered](left, right []T) ([]T, error)

Intersection - intersection of two arrays. Returns new slice.

Example
var (
	intsL = []int{1, 2, 3}
	intsR = []int{1, 2, 4}

	floatsL = []float64{1.1, 2.2, 3.3}
	floatsR = []float64{1.1, 2.2, 4.4}

	strL = []string{"aaa", "bbb", "ccc"}
	strR = []string{"aaa", "bbb", "ddd"}
)

resInts, _ := Intersection(intsL, intsR)
fmt.Println(resInts)

resFloats, _ := Intersection(floatsL, floatsR)
fmt.Println(resFloats)

resStrs, _ := Intersection(strL, strR)
fmt.Println(resStrs)
Output:

[1 2]
[1.1 2.2]
[aaa bbb]

func Round added in v1.1.4

func Round[V float64 | float32](value V, precision int) V

Round - float64 | float32 rounder to certain precision.

Example
var (
	val32 float32 = 0.12345
	val64 float64 = 0.12345
)

res32 := Round(val32, 3)
fmt.Println(res32)
fmt.Println(reflect.TypeOf(res32))

res64 := Round(val64, 3)
fmt.Println(res64)
fmt.Println(reflect.TypeOf(res64))
Output:

0.123
float32
0.123
float64

func RoundFloatStruct added in v1.1.4

func RoundFloatStruct(obj interface{}, precision int) error

RoundFloatStruct - round up float struct fields to certain precision Constraint: simple floats, array and slice. 'obj': ptr struct, fields can be value, not ptr. 'precision': round to.

Example
type Foo struct {
	Field1 float32
	Field2 float64
	Field3 []float32
	Field4 []float64
	Field5 [3]float32
	Field6 [3]float64
	Field7 int    // will be the same
	Field8 string // will be the same
}

foo := &Foo{
	Field1: 1.1111,
	Field2: 2.2222,
	Field3: []float32{1.1111, 2.2222, 3.3333},
	Field4: []float64{4.4444, 5.5555, 7.7777},
	Field5: [3]float32{1.1111, 2.2222, 3.3333},
	Field6: [3]float64{4.4444, 5.5555, 7.7777},
	Field7: 7,
	Field8: "field8",
}

fmt.Printf("%+v\n", *foo)

if err := RoundFloatStruct(foo, 3); err != nil {
	fmt.Println(err)
}

fmt.Printf("%+v", *foo)
Output:

{Field1:1.1111 Field2:2.2222 Field3:[1.1111 2.2222 3.3333] Field4:[4.4444 5.5555 7.7777] Field5:[1.1111 2.2222 3.3333] Field6:[4.4444 5.5555 7.7777] Field7:7 Field8:field8}
{Field1:1.111 Field2:2.222 Field3:[1.111 2.222 3.333] Field4:[4.444 5.556 7.778] Field5:[1.111 2.222 3.333] Field6:[4.444 5.556 7.778] Field7:7 Field8:field8}

func SetAttr

func SetAttr(obj, newValue interface{}, fieldName string) error

SetAttr - set new value on structure field. 'obj': ptr struct, fields can be ptr or value. 'fieldName', 'newValue': value param.

Example
type User struct {
	Username string
}

u := &User{Username: "username"}

if err := SetAttr(u, "new_username", "Username"); err != nil {
	log.Fatal(err)
}

fmt.Println(u.Username)
Output:

new_username

func SetStructAttrs

func SetStructAttrs(curObj, newObj interface{}) error

SetStructAttrs - updates current structure fields with the values of the new structure fields. 'curObj': ptr struct, fields can be ptr or value. 'newObj': value struct, fields can be ptr or value.

Example
type User struct {
	Username string // will change by pte
	Age      int    // will change by value
	Married  bool   // will be the same
}

type NewUser struct {
	Username *string `json:"username"`
	Age      int     `json:"age"`
	Married  *bool   `json:"married"` // nil
}

user := &User{
	Username: "username",
	Age:      30,
	Married:  true,
}

newUserName := "new_username"
newUser := NewUser{
	Username: &newUserName,
	Age:      35,
	Married:  nil,
}

fmt.Printf("%s, %d, %v\n", user.Username, user.Age, user.Married)

if err := SetStructAttrs(user, newUser); err != nil {
	fmt.Println(err)
}

fmt.Printf("%s, %d, %v\n", user.Username, user.Age, user.Married)
Output:

username, 30, true
new_username, 35, true

func SlicesConcat added in v1.1.4

func SlicesConcat[T any](slices ...[]T) []T

SlicesConcat - concatenation of multiple slices.

Example
var (
	ints1 = []int{1, 2, 3}
	ints2 = []int{4, 5, 6}
	ints3 = []int{7, 8, 9}

	strs1 = []string{"1", "2", "3"}
	strs2 = []string{"4", "5", "6"}
	strs3 = []string{"7", "8", "9"}
)

ints := SlicesConcat(ints1, ints2, ints3)
fmt.Println(ints)

strs := SlicesConcat(strs1, strs2, strs3)
fmt.Println(strs)
Output:

[1 2 3 4 5 6 7 8 9]
[1 2 3 4 5 6 7 8 9]

Types

type TimeDelta added in v1.1.4

type TimeDelta struct {
	Years, Months, Days, Hours, Minutes, Seconds, Nanoseconds      int
	TotalMonths, TotalDays, TotalHours, TotalMinutes, TotalSeconds int
}

TimeDelta - the difference between the two dates for each value.

func Elapsed added in v1.1.4

func Elapsed(from, to time.Time) *TimeDelta

Elapsed - Get the time difference from 'from' to 'to'.

Example
var (
	from = time.Date(2022, 5, 25, 1, 1, 1, 1, time.UTC)
	to   = time.Date(2023, 5, 25, 1, 1, 1, 1, time.UTC)
)

res := Elapsed(from, to)
fmt.Println(res.TotalDays)
Output:

365

Jump to

Keyboard shortcuts

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