4

I getting the error not enough arguments in call to method expression AccountService.Open when I run the following. Run here: https://play.golang.org/p/Z9y-QIcwNy

type AccountService interface {
    Open(no string, name string, openingDate time.Time) AccountService
}

type Account struct {
    Num      string
    Name     string
    OpenDate time.Time
    Balance  float64
}

type SavingsAccount struct {
    InterestRate float32
    Account
}

type CheckingAccount struct {
    TransactionFee float32
    Account
}

func (a SavingsAccount) Open(no string, name string, openingDate time.Time) AccountService {
    return SavingsAccount{
        Account: Account{Num: no,
            Name:     name,
            OpenDate: openingDate,
        },
        InterestRate: 0.9,
    }
}
func (a CheckingAccount) Open(no string, name string, openingDate time.Time) AccountService {
    return CheckingAccount{
        Account: Account{Num: no,
            Name:     name,
            OpenDate: openingDate,
        },
        TransactionFee: 0.15,
    }
}

func main() {
    aliceAcct := AccountService.Open("12345", "Alice", time.Date(1999, time.January, 03, 0, 0, 0, 0, time.UTC))

    fmt.Println("Alice's account =", aliceAcct)
}
2

3 Answers 3

7

The result of the method expression AccountService.Open is a function with with type func(AccountService, string, string, time.Time) AccountService. The code is missing the first argument. You can call it like this:

aliceAcct := AccountService.Open(CheckingAccount{}, "12345", "Alice", time.Date(1999, time.January, 03, 0, 0, 0, 0, time.UTC))

playground example

If you have no meaningful value to use as the receiver, then use a function instead:

func OpenCheckingAccount(no string, name string, openingDate time.Time) AccountService {
    ...
}

If you need to abstract account creation, then define the service as a function:

 type AccountService func(no string, name string, openingDate time.Time) AccountType
 func OpenSavings(no string, name string, openingDate time.Time) AccountType { ... }
 func OpenChecking(no string, name string, openingDate time.Time) AccountType { ... }

The OpenSavings and OpenChecking functions can be used as an AccountService.

You will want to use different types for the service and accounts. Here, I use AccountService and AccountType. AccountType is not a very good name, but Account is already used. AccountType might be defined as the following:

type AccountType interface {
   func Deposit(int)
   func Withdraw(int)
}
Sign up to request clarification or add additional context in comments.

2 Comments

Didn't know about the method expression. The error message is clear now. Wish the compiler generated a little bit more verbose/clear error message.
Account is an embedded type within SavingsAccount or CheckingAccount structs. How can OpenSavings(...) and OpenChecking() return Account type?
4

Try this

acct := SavingsAccount{}
aliceAcct:= acct.Open("12345", "Alice", time.Date(1999, time.January, 03, 0, 0, 0, 0, time.UTC))
fmt.Println("Alice's account =", aliceAcct)

You need to create an instance of a struct that properly implements the AccountService interface

--Edit Working example: play.golang.org

1 Comment

Is there an alternate way to organize the code so that I can avoid creating a dummy instance of the struct just to call the methods? Also, why does the error say that an argument is missing?
2

Most Go packages do one of two things:

  1. Have a package level function such as OpenSavingsAccount that returns an open, initialized SavingsAccount.

  2. Have a default variable in the package named DefaultSavingsAccount and duplicate the SavingsAccount methods at the package level where they operate on the DefaultSavingsAccount. This is a lot of function duplication but all of the logic stays in the methods. And if the DefaultSavingsAccount is not const and is an interface type it can be replaced with another implementation.

2 Comments

So the general Idiom in Go is to declare package level constructor functions to initialize structs and use interfaces for other behavior say deposit, credit & transfer? Also, can you please post an e.g. for second point
@AravindR.Yarram: See DefaultClient at golang.org/pkg/net/http/#pkg-variables

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.