如何在结构类型上调用Go方法?

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)
}

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)
}

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

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.