Code generation tools for Go.

interfaces GoDoc Build Status Build status

Code generation tools for Go's interfaces.

Tools available in this repository:

cmd/interfacer GoDoc

Generates an interface for a named type.

Installation

~ $ go get github.com/rjeczalik/interfaces/cmd/interfacer

Usage

~ $ interfacer -help
Usage of interfacer:
  -all
        Include also unexported methods.
  -as string
        Generated interface name. (default "main.Interface")
  -for string
        Type to generate an interface for.
  -o string
        Output file. (default "-")

Example

  • generate by manually
~ $ interfacer -for os.File -as mock.File
  • generate by go generate
//go:generate interfacer -for os.File -as mock.File -o file_iface.go
~ $ go generate  ./...
  • output
// Created by interfacer; DO NOT EDIT

package mock

import (
        "os"
)

// File is an interface generated for "os".File.
type File interface {
        Chdir() error
        Chmod(os.FileMode) error
        Chown(int, int) error
        Close() error
        Fd() uintptr
        Name() string
        Read([]byte) (int, error)
        ReadAt([]byte, int64) (int, error)
        Readdir(int) ([]os.FileInfo, error)
        Readdirnames(int) ([]string, error)
        Seek(int64, int) (int64, error)
        Stat() (os.FileInfo, error)
        Sync() error
        Truncate(int64) error
        Write([]byte) (int, error)
        WriteAt([]byte, int64) (int, error)
        WriteString(string) (int, error)
}

cmd/structer GoDoc

Generates a struct for a formatted file. Currently supported formats are:

  • CSV

Installation

~ $ go get github.com/rjeczalik/interfaces/cmd/structer

Usage

~ $ structer -help
Usage of structer:
  -as string
        Generated struct name. (default "main.Struct")
  -f string
        Input file. (default "-")
  -o string
        Output file. (default "-")
  -tag string
        Name for a struct tag to add to each field.
  -type string
        Type of the input, overwrites inferred from file name.

Example

~ $ head -2 aws-billing.csv         # first line is a CSV header, second - first line of values
"InvoiceID","PayerAccountId","LinkedAccountId","RecordType","RecordID","BillingPeriodStartDate","BillingPeriodEndDate","InvoiceDate"
"Estimated","123456","","PayerLineItem","5433212345","2016/01/01 00:00:00","2016/01/31 23:59:59","2016/01/21 19:19:06"
~ $ structer -f aws-billing.csv -tag json -as billing.Record
// Created by structer; DO NOT EDIT

package billing

import (
        "strconv"
        "time"
)

// Record is a struct generated from "aws-billing.csv" file.
type Record struct {
        InvoiceID              string    `json:"invoiceID"`
        PayerAccountID         int64     `json:"payerAccountID"`
        LinkedAccountID        string    `json:"linkedAccountID"`
        RecordType             string    `json:"recordType"`
        RecordID               int64     `json:"recordID"`
        BillingPeriodStartDate time.Time `json:"billingPeriodStartDate"`
        BillingPeriodEndDate   time.Time `json:"billingPeriodEndDate"`
        InvoiceDate            time.Time `json:"invoiceDate"`
}

// MarshalCSV encodes r as a single CSV record.
func (r *Record) MarshalCSV() ([]string, error) {
        records := []string{
                r.InvoiceID,
                strconv.FormatInt(r.PayerAccountID, 10),
                r.LinkedAccountID,
                r.RecordType,
                strconv.FormatInt(r.RecordID, 10),
                time.Parse("2006/01/02 15:04:05", r.BillingPeriodStartDate),
                time.Parse("2006/01/02 15:04:05", r.BillingPeriodEndDate),
                time.Parse("2006/01/02 15:04:05", r.InvoiceDate),
        }
        return records, nil
}

// UnmarshalCSV decodes a single CSV record into r.
func (r *Record) UnmarshalCSV(record []string) error {
        if len(record) != 8 {
                return fmt.Errorf("invalud number fields: want 8, got %d", len(record))
        }
        r.InvoiceID = record[0]
        if record[1] != "" {
                if val, err := strconv.ParseInt(record[1], 10, 64); err == nil {
                        r.PayerAccountID = val
                } else {
                        return err
                }
        }
        r.LinkedAccountID = record[2]
        r.RecordType = record[3]
        if record[4] != "" {
                if val, err := strconv.ParseInt(record[4], 10, 64); err == nil {
                        r.RecordID = val
                } else {
                        return err
                }
        }
        if record[5] != "" {
                if val, err := time.Parse("2006/01/02 15:04:05", record[5]); err == nil {
                        r.BillingPeriodStartDate = val
                } else {
                        return err
                }
        }
        if record[6] != "" {
                if val, err := time.Parse("2006/01/02 15:04:05", record[6]); err == nil {
                        r.BillingPeriodEndDate = val
                } else {
                        return err
                }
        }
        if record[7] != "" {
                if val, err := time.Parse("2006/01/02 15:04:05", record[7]); err == nil {
                        r.InvoiceDate = val
                } else {
                        return err
                }
        }
        return nil
}
Comments
  • Marking comment should be formed

    Marking comment should be formed "Code generated by xxx"

    ref: https://github.com/github/linguist/blob/master/lib/linguist/generated.rb#L299-L304

    Many of tools to generate go code are marking code with "Code generated by xxx". It's de facto standard.

  • `interfacer` doesn't preserve variadic arguments

    `interfacer` doesn't preserve variadic arguments

    Input struct: "github.com/gocql/gocql".Session

    Output:

    // Session is an interface generated for "github.com/gocql/gocql".Session.
    type Session interface {
    // ...
    	Query(string, []interface{}) *gocql.Query
    // ...
    }
    

    Corresponding function signature (see github.com/gocql/gocql/session.go:

    func (s *Session) Query(stmt string, values ...interface{}) *Query
    
  • Panic when generating interface for redis client

    Panic when generating interface for redis client

    I love the idea of this project! Unfortunately this is what I hit when I tried it out:

    > interfacer -for \"github.com/go-redis/redis\".Client -as mock.redis

    panic: internal: t=*types.Signature, orig=*types.Signature
    
    goroutine 1 [running]:
    panic(0x217c40, 0x429cf5550)
    	$GOROOT/src/runtime/panic.go:500 +0x1a1
    github.com/rjeczalik/interfaces.(*Type).setFromType(0x430661878, 0x367400, 0x425b33290, 0x0, 0x367400, 0x425b33290)
    	$GOPATH/src/github.com/rjeczalik/interfaces/type.go:65 +0x350
    github.com/rjeczalik/interfaces.newType(0x42596d1d0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)
    	$GOPATH/src/github.com/rjeczalik/interfaces/type.go:29 +0x8b
    github.com/rjeczalik/interfaces.buildInterfaceForPkg(0x4204b20b0, 0x430661eb0, 0x7fff5fbfe4e1, 0x19, 0x42582d818, 0x1, 0x0)
    	$GOPATH/src/github.com/rjeczalik/interfaces/interface.go:140 +0x41c
    github.com/rjeczalik/interfaces.buildInterface(0x430661eb0, 0x420433dd8, 0x95de4, 0x7fff5fbfe4e1, 0x21, 0x266bba)
    	$GOPATH/src/github.com/rjeczalik/interfaces/interface.go:84 +0x2c0
    github.com/rjeczalik/interfaces.NewWithOptions(0x430661eb0, 0x21, 0x4204a8060, 0x0, 0x0, 0x4204a2000)
    	$GOPATH/src/github.com/rjeczalik/interfaces/interface.go:45 +0x156
    main.main()
    	$GOPATH/src/github.com/rjeczalik/interfaces/cmd/interfacer/main.go:73 +0xf0
    

    Am I using it wrong or is there a bug here?

  • command not found: interfacer

    command not found: interfacer

    interfacer zsh: command not found: interface

    I am getting this error after installing go get github.com/rjeczalik/interfaces/cmd/interfacer

    Also I am not seeing any binary in my go bin directory /Users/khanakia/go/bin

  • Bug in interfacer - no exported methods found for

    Bug in interfacer - no exported methods found for "Worktree" (package "github.com/go-git/go-git/v5_test")

    When using interfacer on github.com/go-git/go-git/v5.Worktree it failed inconsistently with:

    no exported methods found for "Worktree" (package "github.com/go-git/go-git/v5_test")
    

    I tried to debug interfacer and found out that it loads the definitions from this package in a random order and there are four definitions in this package with the name Worktree, two of those definitions have the type *types.Named so they pass this check, but only one of them has the type methods, which makes if fail if it takes the wrong definition.

    I have implemented a fix and it seems to be working, I can submit a PR if you'd like.

  • Fix fixup function for case that import path of package has different…

    Fix fixup function for case that import path of package has different…

    Initial problem: Parameter of struct function is imported. This imported package folder is different to its package name.

    Example: interfacer -for github.com/minio/minio-go/v6.Client -as contentservice.MinioClient -o minio_client_interface.go

  • Invalid code generated for a method returning map

    Invalid code generated for a method returning map

    interfacer generates invalid response.

    $ cat bar.go
    package foo
    
    import (
            "net/url"
    )
    
    type Bar struct {
    }
    
    func (b *Bar) Map() map[string]url.URL {
            return nil
    }
    $ interfacer -as foo.Foo -for ..Bar
    // Created by interfacer; DO NOT EDIT
    
    package foo
    
    import (
            "net/url"
    )
    
    // Foo is an interface generated for "..Bar".
    type Foo interface {
            Map() map[string]net/url.URL  // This's invalid response
    }```
  • fix fixup when include other package struct

    fix fixup when include other package struct

    When I define method that contain other package struct slice, generated invalid Field interface

    eg)

    // github.com/rjeczalik/interfaces/test/sample
    package sample
    
    import (
        "github.com/rjeczalik/interfaces/test/hoge"
    )
    
    type Sample struct{}
    
    func (s *Sample) Hoges() []*hoge.Hoge { return []*hoge.Hoge{&hoge.Hoge{}} }
    
    interfacer -for 'github.com/rjeczalik/interfaces/test/hoge'.Sample -as hoge.Sampler -o sample.gen.go
    

    generated

    // github.com/rjeczalik/interfaces/test/sample.gen.go
    package sample
    
    type Sampler interface {
      Hoges() *[]github.com/rjeczalik/interfaces/test/hoge.Hoge
    }
    

    refs: https://github.com/rjeczalik/interfaces/issues/13


    so I fixed fixup method

  • When method's response are other package struct slice, generated invalid interface.

    When method's response are other package struct slice, generated invalid interface.

    I use interfacer and it's very useful but I happen this case.

    I define struct like this

    package foo
    
    import (
       "github.com/example/hoge"
    )
    
    type Foo struct {}
    
    func (f *Foo) Hoge1() error { return nil }
    
    func (f *Foo) Hoge2() *hoge.Hoge { return &hoge.Hoge{} }
    
    func (f *Foo) Hoge3() []*hoge.Hoge { return []*hoge.Hoge{...} }
    

    I generate interface using by interfaces like this.

    interfacer -for github.com/Konboi/foo.Foo  -as foo.Fooer -o foo.gen.go
    

    but generated file is like this

    package foo
    
    import (
       "github.com/example/hoge"
    )
    
    type Fooer interface {
        Hoge1() error
        Hoge2() *hoge.Hoge
        Hoge3() []*github.com/example/hoge.Hoge
    }
    

    but I think it should be

    package foo
    
    import (
       "github.com/example/hoge"
    )
    
    type Fooer interface {
        Hoge1() error
        Hoge2() *hoge.Hoge
        Hoge3() []*hoge.Hoge
    }
    

    is it correct ??

    please check it.

  • How do you install?

    How do you install?

    I tried the normal go get github.com/rjeczalik/interfaces and it downloads but it doesn't install anything. A go build in src/github.com/rjeczalik/interfaces doesn't seem to do anything either.

  • Update main.go

    Update main.go

    To convey to humans and machine tools that code is generated, generated source should have a line that matches the following regular expression (in Go syntax):

    ^// Code generated .* DO NOT EDIT\.$
    
  • Interfacer generates invalid code when package name contains hyphen

    Interfacer generates invalid code when package name contains hyphen

    We've tried to run interfacer against github.com/PagerDuty/go-pagerduty.Client. When one of the function arguments is a package name, it generates:

    	ListAuditRecordsPaginated(context.Context, pagerduty.ListAuditRecordsOptions, func(go-pagerduty.AuditRecord) bool) ([]pagerduty.AuditRecord, error)
    

    however, go-pagerduty isn't a valid package name. Would it be possible to pass args to tell interfacer which package name to use in this scenario?

  • Is interfacer supposed to be slow?

    Is interfacer supposed to be slow?

    We have noticed that go generate takes awfully long since we started using interfacer. Compared to mockgen, interfacer seems to take several orders of magnitude longer to run per file.

    Is this by design/unavoidable or is this a bug?

  • feature request: Generate multiple interfaces into the same file

    feature request: Generate multiple interfaces into the same file

    I want to generate interfaces over the GCP Datastore library. This has four structs: Client, Transaction, Iterator, and Commit.

    Ideally I'd like to use interfacer to generate these all into the same target file, perhaps -for and -as could take multiple arguments to a single -o output file.

    Unless I am mistaken, I believe this is not currently possible. It would be a nice feature :)

  • Is it possible to include parameter names when generating an interface using `interfacer`

    Is it possible to include parameter names when generating an interface using `interfacer`

    Is it possible to include parameter names when generating an interface using interfacer?

    Currently, all the function parameter names are stripped so

     FooBar(ctx context.Context, eventContext string, includePrivate bool, includeGeo bool)
    

    becomes

    FooBar(ctx, string, bool, bool)
    

    which is much harder to work with.

  • Interfaces syntactically incorrect for functions with functions as arguments

    Interfaces syntactically incorrect for functions with functions as arguments

    I have my own PubSub package, which has a method SubscribeWithCallback. One of the arguments to this function is a function (used as a callback in this case)...

    func (ps PubSub) SubscribeWithCallback(
    	c context.Context,
    	sub pubsub.Subscription,
    	callback func(context.Context, pubsub.Message),
    ) (context.Context, error) {
    

    When I use go:generate with interfacer on my PubSub struct, the resultant interface is not syntactically correct and will not compile...

    //go:generate interfacer -for github.com/my/repo/pubsub.PubSub -as psiface.PubSub -o psiface/pubsub_iface.go
    

    pubsub_iface.go looks like this:

    // Code generated by interfacer; DO NOT EDIT
    
    package psiface
    
    import (
    	"context"
    	"github.com/my/repo/psiface"
    )
    
    // PubSub is an interface generated for "github.com/my/repo/pubsub.PubSub".
    type PubSub interface {
        ....
    	SubscribeWithCallback(context.Context, pubsub.Subscription, func(context.Context, cloud.google.com/go/internal/pubsub.Message)) (context.Context, error)
    }
    
    

    This has a syntax error as cloud.google.com/go/internal/pubsub.Message is not a valid type.

    It seems that some step must be missing or bugged to handle arguments of functions passed as arguments.

  • Ignore specified embedded fields when generating an interface

    Ignore specified embedded fields when generating an interface

    Would you accept a PR that allows specifying ignored embedded fields?

    My use case:

    type DB struct {
      *underlyingDB.Client
    }
    
    func (db *DB) CreateUser() {}
    

    I'd like to exclude methods from underlyingDB.Client.

    do you think -ignore Field1,Field2 would be a good argument format?

Type-driven code generation for Go

What’s this? gen is a code-generation tool for Go. It’s intended to offer generics-like functionality on your types. Out of the box, it offers offers

Jan 4, 2023
Code Generation for Functional Programming, Concurrency and Generics in Golang

goderive goderive derives mundane golang functions that you do not want to maintain and keeps them up to date. It does this by parsing your go code fo

Dec 25, 2022
Source code of Liteloader Tools

LiteLoader Tools This repository store the source code of some LiteLoader Tools Prebuilt Binary see /bin folder Image2Binary [Golang] convert Image(jp

Aug 30, 2022
Singlestore event analytics - Evaluation of sortable ID generation schemes

Singlestore event analytics - Evaluation of sortable ID generation schemes

Jan 25, 2022
Clean-Swift source and test code auto-generator. It can save you time typing 500-600 lines of code.
Clean-Swift source and test code auto-generator. It can save you time typing 500-600 lines of code.

Clean-Swift source & test code auto generator Overview Run Output Basic Usage make config.yaml target_project_name: Miro // target project name copyri

Apr 13, 2022
Code generator that generates boilerplate code for a go http server

http-bootstrapper This is a code generator that uses go templates to generate a bootstrap code for a go http server. Usage Generate go http server cod

Nov 20, 2021
A directory of hardware related libs, tools, and tutorials for Go

Go + hardware This repo is a directory of tools, packages and tutorials to let you introduce Go in your hardware projects. Why Go? Go can target platf

Dec 30, 2022
gqlanalysis makes easy to develop static analysis tools for GraphQL in Go.
gqlanalysis makes easy to develop static analysis tools for GraphQL in Go.

gqlanalysis gqlanalysis defines the interface between a modular static analysis for GraphQL in Go. gqlanalysis is inspired by go/analysis. gqlanalysis

Dec 14, 2022
gopkg is a universal utility collection for Go, it complements offerings such as Boost, Better std, Cloud tools.

gopkg is a universal utility collection for Go, it complements offerings such as Boost, Better std, Cloud tools. Table of Contents Introduction

Jan 5, 2023
Little Bug Bounty & Hacking Tools⚔️

Little Bug Bounty & Hacking Tools ⚔️

Jan 7, 2023
common tools for golang

utils common tools for golang package main

Dec 27, 2021
Go tools sourcecode read and customize

Go Tools This subrepository holds the source for various packages and tools that support the Go programming language. Some of the tools, godoc and vet

Oct 24, 2021
A fully Go userland with Linux bootloaders! u-root can create a one-binary root file system (initramfs) containing a busybox-like set of tools written in Go.

u-root Description u-root embodies four different projects. Go versions of many standard Linux tools, such as ls, cp, or shutdown. See cmds/core for m

Dec 29, 2022
Mackerel SLI/SLO tools

shimesaba For SRE to operate and monitor services using Mackerel. Description shimesaba is a tool for tracking SLO/ErrorBudget using Mackerel as an SL

Nov 21, 2022
Like tools/cmd/stringer with bitmask features

Bitmasker Bitmasker is a tool used to automate the creation of helper methods when dealing with bitmask-type constant flags. Given the name of an unsi

Nov 25, 2021
Functional tools in Go 1.18 using newly introduced generics

functools functools is a simple Go library that brings you your favourite functi

Dec 5, 2022
Generic-based collection tools

go-collection go collection is a tool implemented using generic, it can help you process slice/map data quickly and easily convert between them. Note:

Dec 29, 2022
Versatile Go code generator.
Versatile Go code generator.

Generis Versatile Go code generator. Description Generis is a lightweight code preprocessor adding the following features to the Go language : Generic

Nov 30, 2022
Golang source code parsing, usage like reflect package

gotype Golang source code parsing, usage like reflect package English 简体中文 Usage API Documentation Examples License Pouch is licensed under the MIT Li

Dec 9, 2022