Sunday, May 12, 2024
HomeGolangNew to Go, code assessment request pls - Code Overview

New to Go, code assessment request pls – Code Overview


I created the next code to assist take away some boilerplate round go routines/channels and in addition make it considerably extra much like how different languages use async/await

just a few questions:

  1. is that this a nasty follow in go? why?
  2. if its okay, is there something I ought to do totally different?
  3. is there a extra full resolution out there for this (I checked pkgs however I’m unsure if my pkg search foo is there but)
bundle process

import (
	"context"
	"fmt"
)

sort TaskStatus int

const (
	New TaskStatus = iota
	Operating
	Accomplished
)

var taskStatus = [3]string{"New", "Operating", "Accomplished"}

sort taskFunc[T interface{}] func(ctx context.Context) (T, error)
sort voidTaskFunc func(ctx context.Context) error

sort Activity[T interface{}] interface {
	Standing() TaskStatus
	Outcome() (T, error)
	Await(ctx ...context.Context) (T, error)
}

sort process[T interface{}] struct {
	outcome T
	err    error
	c      chan struct{}
	standing TaskStatus
	fn     taskFunc[T]
}

sort TaskPanicError struct {
	purpose interface{}
}

func (e TaskPanicError) Error() string {
	return fmt.Sprintf("Activity panicked: %v", e.purpose)
}

func NewTask[T interface{}](fn taskFunc[T]) *process[T] {
	t := new(process[T])
	t.c = make(chan struct{})
	t.fn = fn

	return t
}

func (t *process[T]) Standing() TaskStatus {
	return t.standing
}

func (t *process[T]) Outcome() (T, error) {
	swap t.standing {
	case Accomplished:
		return t.outcome, t.err
	default:
		return t.outcome, fmt.Errorf("Activity standing is %s", taskStatus[t.status])
	}
}

func (t *process[T]) Await(ctx ...context.Context) (T, error) {
	swap t.standing {
	case Accomplished:
		return t.outcome, t.err
	case Operating:
		return t.outcome, fmt.Errorf("Activity already operating, can solely be began as soon as")
	}

	defer func() {
		t.standing = Accomplished
	}()

	var _ctx context.Context
	if len(ctx) == 0 {
		_ctx = context.Background()
	} else {
		_ctx = ctx[0]
	}

	go t.begin(_ctx)

	choose {
	case <-_ctx.Accomplished():
		return t.outcome, _ctx.Err()
	case <-t.c:
		return t.outcome, t.err
	}
}

func (t *process[T]) begin(ctx context.Context) {
	defer func() {
		if r := recuperate(); r != nil {
			t.err = TaskPanicError{purpose: r}
		}

		t.standing = Accomplished
		t.c <- struct{}{}
		shut(t.c)
	}()

	if ctx.Err() != nil {
		t.err = ctx.Err()
		t.c <- struct{}{}
		return
	}

	t.standing = Operating
	t.outcome, t.err = t.fn(ctx)
}

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments