Skip to content

Instantly share code, notes, and snippets.

@killwing
Last active August 13, 2021 04:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save killwing/68f606dbc92615211a636256c49d297c to your computer and use it in GitHub Desktop.
Save killwing/68f606dbc92615211a636256c49d297c to your computer and use it in GitHub Desktop.
golang utils
package duration
import (
"encoding/json"
"fmt"
"time"
)
type Duration struct {
time.Duration
}
func (d Duration) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}
func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
return d.decode(v)
}
func (d Duration) MarshalYAML() (interface{}, error) {
return d.String(), nil
}
func (d *Duration) UnmarshalYAML(unmarshal func(interface{}) error) error {
var v interface{}
if err := unmarshal(&v); err != nil {
return err
}
return d.decode(v)
}
func (d *Duration) decode(v interface{}) error {
switch value := v.(type) {
case float64:
d.Duration = time.Duration(value)
return nil
case string:
var err error
d.Duration, err = time.ParseDuration(value)
if err != nil {
return err
}
return nil
default:
return fmt.Errorf("invalid duration: %v", v)
}
}
func FilterOut(data []int, ids []int) []int {
w := 0
loop:
for _, x := range data {
for _, id := range ids {
if id == x {
continue loop
}
}
data[w] = x
w++
}
return data[:w]
}
func Filter(data []int, ids []int) []int {
w := 0
for _, x := range data {
for _, id := range ids {
if id == x {
data[w] = x
w++
}
}
}
return data[:w]
}
package iochan
import (
"context"
"io"
"sync"
)
var _ io.Reader = (*IOChan)(nil)
var _ io.Writer = (*IOChan)(nil)
var _ io.Closer = (*IOChan)(nil)
type IOChan struct {
ch chan []byte
ctx context.Context
unread []byte
lock sync.Mutex
}
func New(bufn int, ctx context.Context) *IOChan {
return &IOChan{
ch: make(chan []byte, bufn),
ctx: ctx,
}
}
func (t *IOChan) Read(p []byte) (int, error) {
if len(p) == 0 {
return 0, nil
}
// return unread first
t.lock.Lock()
if len(t.unread) != 0 {
n := copy(p, t.unread)
t.unread = t.unread[n:]
t.lock.Unlock()
return n, nil
}
t.lock.Unlock()
select {
case d, ok := <-t.ch:
if !ok {
return 0, io.EOF
}
n := copy(p, d)
t.lock.Lock()
t.unread = d[n:]
t.lock.Unlock()
return n, nil
case <-t.ctx.Done():
close(t.ch)
return 0, t.ctx.Err()
}
}
func (t *IOChan) Write(p []byte) (int, error) {
d := make([]byte, len(p))
copy(d, p)
select {
case t.ch <- d:
return len(p), nil
case <-t.ctx.Done():
close(t.ch)
return 0, t.ctx.Err()
}
}
func (t *IOChan) Close() error {
close(t.ch)
return nil
}
func UnmarshalSlice(raw []json.RawMessage, v interface{}) error {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr || rv.IsNil() {
return fmt.Errorf("can only unmarshal to a pointer of slice type")
}
if rv.Elem().Kind() != reflect.Slice {
return fmt.Errorf("can only unmarshal to a pointer of slice type")
}
s := reflect.MakeSlice(rv.Elem().Type(), 0, len(raw))
for _, r := range raw {
vv := reflect.New(rv.Elem().Type().Elem())
if e := json.Unmarshal(r, vv.Interface()); e != nil {
return e
}
s = reflect.Append(s, vv.Elem())
}
rv.Elem().Set(s)
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment