Реализация интерфейсов Golang

Интерфейсы в Go позволяют написать повторно используемый код. Они широко используются почти во всех проектах Go, и поэтому я постоянно ссылаюсь на разные GODOC, чтобы реализовать интерфейсы в своём проекте. Однако постоянно ссылаясь на документацию, чтобы понять, как полностью реализовать конкретный интерфейс, мы можем потерять много времени.

Golang documentation webpage

Например, довольно часто нужно реализовать хэш-интерфейс, чтобы сделать структуру хэш-таблицей. Вот, например, страница документа для хэша:

Golang documentation for the hash interface

Вместо того, чтобы фиксировать в памяти пять сигнатур методов, необходимых для реализации этого интерфейса, я предлагаю сделать проще.

Используйте impl ⚡️

Impl генерирует заглушки методов для реализации интерфейса. Мы, конечно, упростили, но на самом деле это очень полезно!

Чтобы использовать impl, вам нужно указать имя структуры, для которой вы хотели бы реализовать интерфейс, и само имя интерфейса.

$ impl <struct-name> <interface-name>

Возвращаясь к примеру с хэшем, посмотрим, как мы можем использовать impl, чтобы создать интерфейс.

Запуская impl Foo hash.Hash, мы получаем следующий код:

func (Foo) Write(p []byte) (n int, err error) {
	panic("not implemented") // TODO: Implement
}


func (Foo) Sum(b []byte) []byte {
	panic("not implemented") // TODO: Implement
}


func (Foo) Reset() {
	panic("not implemented") // TODO: Implement
}


func (Foo) Size() int {
	panic("not implemented") // TODO: Implement
}


func (Foo) BlockSize() int {
	panic("not implemented") // TODO: Implement
}

Теперь представьте, что в будущем наша структура Foo должна быть не только хэшируемой, но и сортируемой. Не проблема, мы можем использовать impl, чтобы заглушить реализацию интерфейса сортировки!

$ impl Foo sort.Interface

Аналогично, получаем методы, необходимые для реализации сортировки!


func (Foo) Len() int {
	panic("not implemented") // TODO: Implement
}


func (Foo) Less(i int, j int) bool {
	panic("not implemented") // TODO: Implement
}


func (Foo) Swap(i int, j int) {
	panic("not implemented") // TODO: Implement
}

impl можно использовать не только, чтобы создать стандартные библиотечные интерфейсы, но и чтобы отключить любой интерфейс! Например, go-mysql предлагает мощный набор инструментов для взаимодействия с базами данных MySQL в Go. Мы можем легко использовать impl для реализации интерфейса обработчика в go-mysql.

$ go get github.com/siddontang/go-mysql/server
$ impl Foo server.Handler

func (Foo) UseDB(dbName string) error {
	panic("not implemented") // TODO: Implement
}


func (Foo) HandleQuery(query string) (*server.Result, error) {
	panic("not implemented") // TODO: Implement
}


func (Foo) HandleFieldList(table string, fieldWildcard string) ([]*server.Field, error) {
	panic("not implemented") // TODO: Implement
}


func (Foo) HandleStmtPrepare(query string) (params int, columns int, context interface{}, err error) {
	panic("not implemented") // TODO: Implement
}


func (Foo) HandleStmtExecute(context interface{}, query string, args []interface{}) (*server.Result, error) {
	panic("not implemented") // TODO: Implement
}


func (Foo) HandleStmtClose(context interface{}) error {
	panic("not implemented") // TODO: Implement
}


func (Foo) HandleOtherCommand(cmd byte, data []byte) error {
	panic("not implemented") // TODO: Implement
}

На этом всё. Спасибо, что прочитали! 👋

Ответить