• Stars
    star
    1,151
  • Rank 38,958 (Top 0.8 %)
  • Language
    Go
  • License
    Apache License 2.0
  • Created about 7 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Derives and generates mundane golang functions that you do not want to maintain yourself

goderive

Build Status Go Report Card GoDoc

goderive derives mundane golang functions that you do not want to maintain and keeps them up to date.

Watch the video

It does this by parsing your go code for functions, which are not implemented, and then generates these functions for you by deriving their implementations from the input parameter types.

Examples

In the following code the deriveEqual function will be spotted as a function that was not implemented (or was previously derived) and has a prefix deriveEqual.

package main

type MyStruct struct {
	Int64     int64
	StringPtr *string
}

func (this *MyStruct) Equal(that *MyStruct) bool {
	return deriveEqual(this, that)
}

goderive will then generate the following code in a derived.gen.go file in the same package:

func deriveEqual(this, that *MyStruct) bool {
	return (this == nil && that == nil) ||
		this != nil && that != nil &&
			this.Int64 == that.Int64 &&
			((this.StringPtr == nil && that.StringPtr == nil) ||
        (this.StringPtr != nil && that.StringPtr != nil && *(this.StringPtr) == *(that.StringPtr)))
}

Recursive Examples:

Set Examples:

Functional Examples:

Concurrency Examples:

Functions

Recursive Functions:

  • Equal
    • deriveEqual(T, T) bool
    • deriveEqual(T) func(T) bool
  • Compare
    • deriveCompare(T, T) int
    • deriveCompare(T) func(T) int
  • DeepCopy
    • deriveDeepCopy(dst *T, src *T)
    • deriveDeepCopy(dst []T, src []T)
    • deriveDeepCopy(dst map[A]B, src map[A]B)
  • Clone deriveClone(T) T
  • GoString deriveGoString(T) string
  • Hash deriveHash(T) uint64

Set Functions:

  • Keys deriveKeys(map[K]V) []K
  • Sort deriveSort([]T) []T
  • Unique deriveUnique([]T) []T
  • Set deriveSet([]T) map[T]struct{}
  • Min
    • deriveMin(list []T, default T) (min T)
    • deriveMin(T, T) T
  • Max
    • deriveMax(list []T, default T) (max T)
    • deriveMax(T, T) T
  • Contains deriveContains([]T, T) bool
  • Intersect
    • deriveIntersect(a, b []T) []T
    • deriveIntersect(a, b map[T]struct{}) map[T]struct{}
  • Union
    • deriveUnion(a, b []T) []T
    • deriveUnion(a, b map[T]struct{}) map[T]struct{}

Functional Functions:

  • Fmap
    • deriveFmap(func(A) B, []A) []B
    • deriveFmap(func(rune) B, string) []B
    • deriveFmap(func(A) B, func() (A, error)) (B, error)
    • deriveFmap(func(A) (B, error), func() (A, error)) (func() (B, error), error)
    • deriveFmap(func(A), func() (A, error)) error
    • deriveFmap(func(A) (B, c, d, ...), func() (A, error)) (func() (B, c, d, ...), error)
  • Join
    • deriveJoin([][]T) []T
    • deriveJoin([]string) string
    • deriveJoin(func() (T, error), error) func() (T, error)
    • deriveJoin(func() (T, ..., error), error) func() (T, ..., error)
  • Filter deriveFilter(pred func(T) bool, []T) []T
  • All deriveAll(pred func(T) bool, []T) bool
  • Any deriveAny(pred func(T) bool, []T) bool
  • TakeWhile deriveTakeWhile(pred func(T) bool, []T) []T
  • Flip deriveFlip(f func(A, B, ...) T) func(B, A, ...) T
  • Curry deriveCurry(f func(A, B, ...) T) func(A) func(B, ...) T
  • Uncurry deriveUncurry(f func(A) func(B, ...) T) func(A, B, ...) T
  • Tuple deriveTuple(A, B, ...) func() (A, B, ...)
  • Compose
    • deriveCompose(func() (A, error), func(A) (B, error)) func() (B, error)
    • deriveCompose(func(A) (B, error), func(B) (C, error)) func(A) (C, error)
    • deriveCompose(func(A...) (B..., error), func(B...) (C..., error)) func(A...) (C..., error)
    • deriveCompose(func(A...) (B..., error), ..., func(C...) (D..., error)) func(A...) (D..., error)
  • Mem
    • deriveMem(func(A...) (B...)) func(A...) (B...)
  • Traverse
    • deriveTraverse(func(A) (B, error), []A) ([]B, error)
  • ToError
    • deriveToError(error, func(A...) (B..., bool)) func(A...) (B..., error)
    • deriveToError(error, func() bool) func() error
  • Apply deriveApply(f func(...A, B) C, B) func(...A) C

Concurrency Functions:

  • Fmap
    • deriveFmap(func(A) B, <-chan A) <-chan B
  • Join
    • deriveJoin(<-chan <-chan T) <-chan T
    • deriveJoin(chan <-chan T) <-chan T
    • deriveJoin([]<-chan T) <-chan T
    • deriveJoin([]chan T) <-chan T
    • deriveJoin(chan T, chan T, ...) <-chan T
  • Pipeline
    • derivePipeline(func(A) <-chan B, func(B) <-chan C) func(A) <-chan C
  • Do
    • deriveDo(func() (A, error), func (B, error)) (A, B, error)
  • Dup
    • deriveDup(c <-chan T) (c1, c2 <-chan T)

When goderive walks over your code it is looking for a function that:

  • was not implemented (or was previously derived) and
  • has a predefined prefix.

Functions which have been previously derived will be regenerated to keep them up to date with the latest modifications to your types. This keeps these functions, which are truly mundane to write, maintainable.

For example when someone in your team adds a new field to a struct and forgets to update the CopyTo method. This problem is solved by goderive, by generating generated functions given the new types.

Function prefixes are by default deriveCamelCaseFunctionName, for example deriveEqual. These are customizable using command line flags.

You can derive functions for different types by using different suffixes with the same prefix. For example, if you wish to derive Equal for types MyStruct and MySecondStruct, name the functions deriveEqualMyStruct and deriveEqualMySecondStruct and goderive will derive both.

Let goderive edit your function names in your source code, by enabling autoname and dedup using the command line flags. These flags respectively make sure that your functions have unique names and that you don't generate multiple functions that do the same thing.

How to run

install the latest version of goderive globally using:

go install github.com/awalterschulze/goderive@latest

goderive can be run from the command line:

goderive ./...

, using the same path semantics as the go tool.

You can also run goderive using go generate

And you can customize specific function prefixes

Or you can customize all function prefixes

You can let goderive rename your functions using the -autoname and -dedup flags. If these flags are not used, goderive will not touch your code and rather return an error.

Customization

The derive package allows you to create your own code generator plugins, see all the current plugins for examples.

You can also create your own vanity binary. Including your own generators and/or customization of function prefixes, etc. This should be easy to figure out by looking at main.go

Inspired By

Users

These projects use goderive:

Please let us know if you are using goderive by opening an issue or a pull request that adds your project to the list.

Mentioned

Please let us know if you mention goderive in a blog post, talk or go experience report, so that we can add a link to our list.

Presentations

More Repositories

1

gographviz

Parses the Graphviz DOT language in golang
Go
538
star
2

learning

A list of videos, playlists, blog posts, papers, books, etc. that I have learned from and still intend to learn from.
158
star
3

category-theory-for-programmers-challenges

Challenges from Category Theory for Programmers
Haskell
112
star
4

gominikanren

a Go implementation of miniKanren, an embedded Domain Specific Language for logic programming.
Go
36
star
5

ragax

A Talk on Ragalur Expressions
JavaScript
25
star
6

regex-reexamined-coq

Coq
19
star
7

the-little-typer-exercises

exercises for the book - the little typer
Racket
16
star
8

goanalysis

GoAnalysis does simple analysis of your source code.
Go
7
star
9

gofuncyourself

A lesson in how to write go code like a motherfuncer
Go
7
star
10

sublime-gocc-syntax

[Deprecated] Sublime Syntax Highlighting for Gocc BNF
5
star
11

git-anchor

[Deprecated] anchors the versions of your git dependencies
Go
5
star
12

parsing-in-go-example

Parsing in Go Examples for Talk
Go
4
star
13

nogotovogo

A First Lesson in using Go
Go
4
star
14

xhaskell-library

Automatically exported from code.google.com/p/xhaskell-library
Haskell
3
star
15

gorangecheck

Go
3
star
16

picolang

pico services as a programming language
Go
3
star
17

proofs-written-by-ai

Proofs written by AI
Makefile
3
star
18

grpcdemo

Another grpc demo
Go
2
star
19

waltercv

walter schulze's curriculum vitae
TeX
2
star
20

coq_in_a_hurry_exercises

Coq in a Hurry - Exercises
Coq
2
star
21

ccc-talk

Correct Code by Construction talk's code
Makefile
2
star
22

awalterschulze.github.io

Walter Schulze's home page
JavaScript
2
star
23

awalterschulze

1
star
24

Friendface

[deprecated] A Social Network built on Github
HTML
1
star
25

advertising-coq

Presentation: Advertising Coq - Proving is Programming
Coq
1
star