Список полезных ресурсов для изучения Go
https://www.notion.so/wdesert/Let-My-Gophers-Go-29d7e8fe712141cf8ac39b84350f0db7
Список ресурсов, который я делал для себя где-то год назад. Возможно, это чрезмерная любовь к структурированию информации и спискам, но мне так обычно проще.
Список может кому-то показаться полезным. В ближайшее время планирую добавить туда несколько классных постов
https://www.notion.so/wdesert/Let-My-Gophers-Go-29d7e8fe712141cf8ac39b84350f0db7
Список ресурсов, который я делал для себя где-то год назад. Возможно, это чрезмерная любовь к структурированию информации и спискам, но мне так обычно проще.
Список может кому-то показаться полезным. В ближайшее время планирую добавить туда несколько классных постов
wdesert on Notion
Let My Gophers Go!
Official Resources
🔥3
Копирование T, когда методы определены с *T — получателем
Если резюмировать:
— Копирование инстансов типа
— Если же есть хоть один метод типа
В качестве примера приводится
С другой стороны, мне по-прежнему кажется, что стоило бы в этом параграфе сделать маленькую оговорку: даже отсутствие методов с получателем типа
Если речь идет о так называемых reference-типах (например, map или slice), независимо от методов мы можем изменить структуру данных, на которые ссылается указатель.
Кстати, Роб Пайк предлагал про это поведение дополнительно рассказать в спецификации:
https://github.com/golang/go/issues/5083
В целом, не мне, конечно, критиковать то, что написали Донован и Керниган, но есть ощущение, что на самом деле имелось в виду следующее: если в API методы определены с value-получателем, это означает/намекает/подсказывает (но формально НЕ гарантирует), что копирование безопасно и не приведет к нежелательным мутациям в структурах данных.
А это ещё один повод перечитать пост Билла Кеннеди про data & semantics:
https://www.ardanlabs.com/blog/2017/06/design-philosophy-on-data-and-semantics.html
6.2 Methods with a Pointer Receiver
If all the methods of a named type T have a receiver type of T itself (not *T ), it is safe to copy instances of that type; calling any of its methods necessarily makes a copy. For example, time.Duration values are liberally copied, including as arguments to functions. But if any method has a pointer receiver, you should avoid copying instances of T because doing so may violate internal invariants. For example, copying an instance of bytes.Buffer would cause the original and the copy to alias ( §2.3.2 ) the same underlying array of bytes. Subsequent method calls would have unpredictable effects.
(The Go Programming Language Alan A. A. Donovan · Brian W. Kernighan)
Если резюмировать:
— Копирование инстансов типа
T, если все методы определены с получателем типа *T, безопасно — Если же есть хоть один метод типа
func (*T), подобное копирование следует избегать, потому что возможны "неожиданные" изменения внутренних инвариантов. В качестве примера приводится
bytes.Buffer, который выглядит так:type Buffer struct {
buf []byte // contents are the bytes buf[off : len(buf)]
off int // read at &buf[off], write at &buf[len(buf)]
lastRead readOp // last read operation, so that Unread* can work correctly.
}
Копирование инстансов типа bytes.Buffer создает алиасы для одного и того же массива под капотом слайса. Последующие вызовы методов — а они как раз определены как func (b *Buffer), могут привести к неожиданным результатам. С другой стороны, мне по-прежнему кажется, что стоило бы в этом параграфе сделать маленькую оговорку: даже отсутствие методов с получателем типа
*T не гарантирует отсутствие внезапных изменений. Если речь идет о так называемых reference-типах (например, map или slice), независимо от методов мы можем изменить структуру данных, на которые ссылается указатель.
Кстати, Роб Пайк предлагал про это поведение дополнительно рассказать в спецификации:
https://github.com/golang/go/issues/5083
В целом, не мне, конечно, критиковать то, что написали Донован и Керниган, но есть ощущение, что на самом деле имелось в виду следующее: если в API методы определены с value-получателем, это означает/намекает/подсказывает (но формально НЕ гарантирует), что копирование безопасно и не приведет к нежелательным мутациям в структурах данных.
А это ещё один повод перечитать пост Билла Кеннеди про data & semantics:
https://www.ardanlabs.com/blog/2017/06/design-philosophy-on-data-and-semantics.html
GitHub
spec: reference-like properties of channels, slices, and maps not well specified · Issue #5083 · golang/go
Although other documents such as Effective Go are clear on the subject, the spec is unclear on the sharing that occurs when channels, maps and slices are assigned to other variables such as through...
О канале
Кто-то однажды сказал, что лучший способ разобраться в предмете — не задать вопрос, а опубликовать абсолютно неверный ответ :)
Цели вводить в заблуждение у меня, конечно, нет, но мотивация похожая. Как понятно из описания канала, ни о какой авторитетности с моей стороны и речи быть не может. В канале я буду писать обо всем, в чем мне лично хотелось бы разобраться/не кажется очевидным. Я достаточно усерден (а иногда и чрезмерно дотошен) в плане ресерча и устранения неопределенности, поэтому таких моментов может быть достаточно много.
Обычное чтение не так хорошо работает, так как велик риск ничего не запомнить и споткнуться о тот же самый вопрос в будущем (проверено).
Другое дело — записывать как сам вопрос, так и свой "ответ" с результатами маленького исследования вопроса, к которым всегда можно вернуться. В общем, даже самый тупой карандаш лучше самой острой памяти :)
Прошу воспринимать все написанное здесь максимально строго и критично. Любой фидбэк крайне приветствуется, ведь именно это и является целью канала.
В свою очередь, буду периодически делиться всем полезным и интересным, что нахожу про Go (или не только). Читаю я регулярно, много, на двух языках, поэтому можно ожидать обновлений.
Let My Gophers Go! :)
Кто-то однажды сказал, что лучший способ разобраться в предмете — не задать вопрос, а опубликовать абсолютно неверный ответ :)
Цели вводить в заблуждение у меня, конечно, нет, но мотивация похожая. Как понятно из описания канала, ни о какой авторитетности с моей стороны и речи быть не может. В канале я буду писать обо всем, в чем мне лично хотелось бы разобраться/не кажется очевидным. Я достаточно усерден (а иногда и чрезмерно дотошен) в плане ресерча и устранения неопределенности, поэтому таких моментов может быть достаточно много.
Обычное чтение не так хорошо работает, так как велик риск ничего не запомнить и споткнуться о тот же самый вопрос в будущем (проверено).
Другое дело — записывать как сам вопрос, так и свой "ответ" с результатами маленького исследования вопроса, к которым всегда можно вернуться. В общем, даже самый тупой карандаш лучше самой острой памяти :)
Прошу воспринимать все написанное здесь максимально строго и критично. Любой фидбэк крайне приветствуется, ведь именно это и является целью канала.
В свою очередь, буду периодически делиться всем полезным и интересным, что нахожу про Go (или не только). Читаю я регулярно, много, на двух языках, поэтому можно ожидать обновлений.
Let My Gophers Go! :)
Let My Gophers Go! pinned «О канале Кто-то однажды сказал, что лучший способ разобраться в предмете — не задать вопрос, а опубликовать абсолютно неверный ответ :) Цели вводить в заблуждение у меня, конечно, нет, но мотивация похожая. Как понятно из описания канала, ни о какой авторитетности…»
Pass by value
Интересно, что в некоторых туториалах и постах про Go по-прежнему пытаются объяснить поведение кода, используя фразу "passed by reference".
Go FAQ весьма недвусмысленно констатирует:
https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go
Наверное, именно эта статья навсегда закрыла этот вопрос для меня и отбила желание искать некорректные аналогии.
С другой стороны, раз уж я пришел в Go из Python, стоит ещё отметить интересный момент: в Питоне тоже все передается по значению, с одной маленькой ремаркой: каждое значение является референсом.
В английском это звучит более складно и смешнее: everything in Python is passed by value, but all values are references :)
Я бы позволил себе смелость заявить, что Питон в каком-то смысле делает выбор за программиста и лишает возможности выбрать (и тут в канал влетает Bill Kennedy) семантику. При всей любви к Питону, мне больше нравится иметь возможность самому сделать выбор, а также лучше понимать, что на самом деле будет происходить.
Интересно, что в некоторых туториалах и постах про Go по-прежнему пытаются объяснить поведение кода, используя фразу "passed by reference".
Go FAQ весьма недвусмысленно констатирует:
As in all languages in the C family, everything in Go is passed by valueНет никакого pass by reference в Go, о чем кратко, но очень понятно написал Dave Cheney:
https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go
Наверное, именно эта статья навсегда закрыла этот вопрос для меня и отбила желание искать некорректные аналогии.
С другой стороны, раз уж я пришел в Go из Python, стоит ещё отметить интересный момент: в Питоне тоже все передается по значению, с одной маленькой ремаркой: каждое значение является референсом.
В английском это звучит более складно и смешнее: everything in Python is passed by value, but all values are references :)
Я бы позволил себе смелость заявить, что Питон в каком-то смысле делает выбор за программиста и лишает возможности выбрать (и тут в канал влетает Bill Kennedy) семантику. При всей любви к Питону, мне больше нравится иметь возможность самому сделать выбор, а также лучше понимать, что на самом деле будет происходить.
👍2
Zen of Go
Очень велик соблазн узнать, как писать идиоматичный, каноничный код на Go (да и вообще в целом).
Этот вопрос неоднократно появляется у меня, неоднократно всплывает на reddit.com/r/golang, и ответ обычно сводится к следующему:
— Прочитать Effective Go
— Прочитать Go Code Review Comments
— Посмотреть и прочитать Go Proverbs
— Почитать исходники
— Обратить внимание на upspin (авторитетно, потому что у истоков стояли Rob Pike и Andrew Gerrand)
— Обратить внимание на проекты в репозитории Hashicorp (не берусь судить), но их часто рекомендуют в качестве "хорошего кода на Go"
Обычно я почти ко всем источникам возвращаюсь по мере усвоения информации, и в этом случае происходит то же самое: не один раз перечитал Effective Go и Go Code Review Comments (и продолжаю, безусловно) — и каждый раз кажется, что в
Но за всеми рекомендациями и "пословицами" в мире Go, которые сформулировал Роб Пайк, стоят более крупные сущности — ключевые ценности и принципы языка и экосистемы. Так называемый "Go-дзен".
Питонисты знают о "пасхалке" в виде
— Beautiful is better than ugly
— Explicit is better than implicit
— Simple is better than complex, etc.
Dave Cheney (кажется, я, как и многие, его фанат) очень интересно проводит параллели и пытается найти соответствующие идиомы и принципы в Go. Примеров кода почти нет, но все равно познавательно.
https://dave.cheney.net/2020/02/23/the-zen-of-go
P.S. Возьму на себя смелость и скажу, что в какой-то момент кажется, что Go в большей степени соответствует "дзену" Питерса, чем сам Питон 🤷♂️
Очень велик соблазн узнать, как писать идиоматичный, каноничный код на Go (да и вообще в целом).
Этот вопрос неоднократно появляется у меня, неоднократно всплывает на reddit.com/r/golang, и ответ обычно сводится к следующему:
— Прочитать Effective Go
— Прочитать Go Code Review Comments
— Посмотреть и прочитать Go Proverbs
— Почитать исходники
— Обратить внимание на upspin (авторитетно, потому что у истоков стояли Rob Pike и Andrew Gerrand)
— Обратить внимание на проекты в репозитории Hashicorp (не берусь судить), но их часто рекомендуют в качестве "хорошего кода на Go"
Обычно я почти ко всем источникам возвращаюсь по мере усвоения информации, и в этом случае происходит то же самое: не один раз перечитал Effective Go и Go Code Review Comments (и продолжаю, безусловно) — и каждый раз кажется, что в
i+1-й раз понял написанное лучше или вообще иначе, нежели в i-й. Но за всеми рекомендациями и "пословицами" в мире Go, которые сформулировал Роб Пайк, стоят более крупные сущности — ключевые ценности и принципы языка и экосистемы. Так называемый "Go-дзен".
Питонисты знают о "пасхалке" в виде
import this, которая содержит "дзен Питона", разработанный Тимом Питерсом. Например: — Beautiful is better than ugly
— Explicit is better than implicit
— Simple is better than complex, etc.
Dave Cheney (кажется, я, как и многие, его фанат) очень интересно проводит параллели и пытается найти соответствующие идиомы и принципы в Go. Примеров кода почти нет, но все равно познавательно.
https://dave.cheney.net/2020/02/23/the-zen-of-go
P.S. Возьму на себя смелость и скажу, что в какой-то момент кажется, что Go в большей степени соответствует "дзену" Питерса, чем сам Питон 🤷♂️
👍2
Go Method Sets
Уже в Tour of Go можно узнать, что Go достаточно либерален в плане вызова методов, поэтому все 4 вызова ниже возможны:
Более того, для addressable типов можно не писать
Как говорит Bill Kennedy, "Go loves you" :)
Тем не менее, поведение ниже меня в первый раз удивило:
Читаем спецификацию:
Снова читаем спецификацию:
Отдельный пункт про method sets есть и в Go FAQ:
Передаем указатель сами и все снова работает:
Уже в Tour of Go можно узнать, что Go достаточно либерален в плане вызова методов, поэтому все 4 вызова ниже возможны:
type Point struct{ X, Y float64 }
func (p Point) Distance(q Point) float64 {
...
}
func (p *Point) ScaleBy(factor float64) {
...
}
p := Point{1, 2}
q := Point{1, 1}
pptr := &Point{1, 2}
p.Distance(q)
p.ScaleBy(2)
pptr.Distance(q)
pptr.ScaleBy(2)
Причина достаточно проста и описана в спецификации:The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T)
A method call x.m() is valid if the method set of (the type of) x contains m and the argument list can be assigned to the parameter list of m. If x is addressable and &x's method set contains m, x.m() is shorthand for (&x).m()
Если коротко, "множество методов" для типа *T включает в себя множество методов, определенных как с T, так и *T получателем. Это логично, ведь всегда можно получить значение, разыменовав указатель. Поэтому на самом деле вызов pptr.Distance(q) будет преобразовано в (*pptr).Distance(q). Более того, для addressable типов можно не писать
(&x)., компилятор сделает это за нас. Как говорит Bill Kennedy, "Go loves you" :)
Тем не менее, поведение ниже меня в первый раз удивило:
type Vectorizer interface {
Distance(q Point) float64
ScaleBy(factor float64)
}
var _ Vectorizer = p
./prog.go:33:6: cannot use p (type Point) as type Vectorizer in assignment:
Point does not implement Vectorizer (ScaleBy method has pointer receiver)
Текст ошибки весьма однозначно описывает проблему: "... Point does not implement Vectorizer (ScaleBy method has pointer receiver)". Починить достаточно просто — var _Vectorizer = &p, но интереснее всего понять причину ошибки. Читаем спецификацию:
A value x is assignable to a variable of type T ("x is assignable to T") if one of the following conditions applies:
...
T is an interface type and x implements T
Даже это ещё не все. Даже если бы такое присвоение было корректным, не выполняется условие из параграфа Method calls: If x is addressable... Снова читаем спецификацию:
The operand must be addressable, that is, either a variable, pointer indirection, or slice indexing operation; or a field selector of an addressable struct operand; or an array indexing operation of an addressable array. As an exception to the addressability requirement, x may also be a (possibly parenthesized) composite literal. If the evaluation of x would cause a run-time panic, then the evaluation of &x does too.Интерфейсы не являются addressable типом.
Отдельный пункт про method sets есть и в Go FAQ:
Even in cases where the compiler could take the address of a value to pass to the method, if the method modifies the value the changes will be lost in the caller. As an example, if the Write method of bytes.Buffer used a value receiver rather than a pointer, this code:В отличие от предыдущего случая, здесь имеем переменную
var buf bytes.Buffer
io.Copy(buf, os.Stdin)
would copy standard input into a copy of buf, not into buf itself. This is almost never the desired behavior.
buf, которая (см. цитату выше) является addressable. Потенциально компилятор может взять адрес переменной и совершить свою маленькую магию, но это будет означать, что копирование произойдет в копию buf, а исходная переменная никакие изменения не увидит. Передаем указатель сами и все снова работает:
io.Copy(&buf, os.Stdin)
Effective Go этот момент тоже комментирует:This rule arises because pointer methods can modify the receiver; invoking them on a value would cause the method to receive a copy of the value, so any modifications would be discarded. The language therefore disallows this mistake.Теперь кажется, что стоило всего лишь раз внимательно прочитать спецификацию, но разве герои идут в обход :)
🔥6👍3
Clean Architecture: The Go Way
"Clean architecture" — философский камень программирования, про который почти регулярно спрашивают на
Саму книгу я несколько раз честно пытался читать, но все время было ощущение, что можно было вполне обойтись одной статьей.
Про чистую архитектуру в Go написано немало, но от некоторых постов и якобы "правильных" реализаций складывалось ощущение, что это действительно слишком сложно, абстракции ради абстракций. В общем, Роб Пайк бы не одобрил. Simplicity is complicated.
Какие ресурсы показались мне понятными/адекватными/занятными:
— https://appliedgo.net/di/
Статья от Christoph Berger про dependency injection (когда-то я купил курс Кристофа Applied Go, который в целом очень рекомендую). Никаких революционных мыслей, немного игрушечные примеры, но все очень понятно и доступно, с мотивацией, когда в конце поста ты не просто запомнил классные английские словосочетания, но ещё и понял, зачем это применять на практике.
— https://dave.cheney.net/2016/08/20/solid-go-design
Dave Cheney размышляет о принципах SOLID в контексте Go.
— https://www.calhoun.io/moving-towards-domain-driven-design-in-go/
Jon Calhoun достаточно известен своими курсами, а в этой статье размышляет на тему DDD и Clean Architecture.
— https://changelog.com/gotime/102
Очень крутой эпизод Go Time с Peter Bourgon (который недавно стал persona non grata из-за чрезмерной любви к троллингу), Kat Zien и Ben Johnson.
— https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1#.o681bumjb
Кстати о Бене Джонсоне: этот его пост обычно первым делом рекомендуют в ответ на вопрос об организации кода.
— https://www.ardanlabs.com/blog/2017/02/design-philosophy-on-packaging.html
Куда же без мнения Билла Кеннеди.
— https://threedots.tech/go-with-the-domain/
Бесплатная книга Go With the Domain — объясняет DDD и Clean Architecture в процессе рефакторинга реального приложения (только начал читать, если книга — отстой, пишите в комментариях)
Интересно, что, если загуглить "Go project layout", первой же ссылкой видим Standard Go Project Layout . И тут же второй ссылкой — тикет от Russ Cox, где Расс сожалеет о том, что эту ссылку многие считают официальной рекомендацией :)
Если знаете другие классные на ваш взгляд материалы, буду благодарен, если поделитесь в комментариях 😊
"Clean architecture" — философский камень программирования, про который почти регулярно спрашивают на
reddit.com/r/golang, а ответ обычно сводится либо к (отчасти необъяснимой) ненависти к Uncle Bob, либо к раздражению в связи с попыткой чрезмерно усложнить Go и привнести в него кусочки Java. Саму книгу я несколько раз честно пытался читать, но все время было ощущение, что можно было вполне обойтись одной статьей.
Про чистую архитектуру в Go написано немало, но от некоторых постов и якобы "правильных" реализаций складывалось ощущение, что это действительно слишком сложно, абстракции ради абстракций. В общем, Роб Пайк бы не одобрил. Simplicity is complicated.
Какие ресурсы показались мне понятными/адекватными/занятными:
— https://appliedgo.net/di/
Статья от Christoph Berger про dependency injection (когда-то я купил курс Кристофа Applied Go, который в целом очень рекомендую). Никаких революционных мыслей, немного игрушечные примеры, но все очень понятно и доступно, с мотивацией, когда в конце поста ты не просто запомнил классные английские словосочетания, но ещё и понял, зачем это применять на практике.
— https://dave.cheney.net/2016/08/20/solid-go-design
Dave Cheney размышляет о принципах SOLID в контексте Go.
— https://www.calhoun.io/moving-towards-domain-driven-design-in-go/
Jon Calhoun достаточно известен своими курсами, а в этой статье размышляет на тему DDD и Clean Architecture.
— https://changelog.com/gotime/102
Очень крутой эпизод Go Time с Peter Bourgon (который недавно стал persona non grata из-за чрезмерной любви к троллингу), Kat Zien и Ben Johnson.
— https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1#.o681bumjb
Кстати о Бене Джонсоне: этот его пост обычно первым делом рекомендуют в ответ на вопрос об организации кода.
— https://www.ardanlabs.com/blog/2017/02/design-philosophy-on-packaging.html
Куда же без мнения Билла Кеннеди.
— https://threedots.tech/go-with-the-domain/
Бесплатная книга Go With the Domain — объясняет DDD и Clean Architecture в процессе рефакторинга реального приложения (только начал читать, если книга — отстой, пишите в комментариях)
Интересно, что, если загуглить "Go project layout", первой же ссылкой видим Standard Go Project Layout . И тут же второй ссылкой — тикет от Russ Cox, где Расс сожалеет о том, что эту ссылку многие считают официальной рекомендацией :)
Если знаете другие классные на ваш взгляд материалы, буду благодарен, если поделитесь в комментариях 😊
👍9🔥1
Functional Options in Go
Прочитал статью про различные способы инициализации структуры и вспомнил про другую от Dave Cheney.
В этот раз написал пост в виде странички Notion, потому что там и писать удобнее, да и выглядит аккуратнее.
Поставьте 🤮 под этим сообщением, если читать так неудобно, или это привело к тому, что вы даже не стали открывать страницу :)
https://wdesert.notion.site/Functional-Options-in-Go-ebb47f62f6ae46ffa3c76ec76aba645a
Прочитал статью про различные способы инициализации структуры и вспомнил про другую от Dave Cheney.
В этот раз написал пост в виде странички Notion, потому что там и писать удобнее, да и выглядит аккуратнее.
Поставьте 🤮 под этим сообщением, если читать так неудобно, или это привело к тому, что вы даже не стали открывать страницу :)
https://wdesert.notion.site/Functional-Options-in-Go-ebb47f62f6ae46ffa3c76ec76aba645a
wdesert on Notion
Functional Options in Go
Прочитал статью про различные способы инициализации структуры и вспомнил про другую от Dave Cheney.
🤮15👍12
Занудство о методах и попытки понять Расса
Читал вчера статью Russ Cox об интерфейсах. Использую несовершенную форму глагола, потому что, несмотря на понимание в общих чертах, не могу сказать, что усвоил написанное (когда-нибудь придется сделать перевод-пересказ, чтобы проверить своё понимание).
Споткнулся, к своему сожалению, достаточно рано (см. изображение).
Когда речь зашла о списке указателей на функции, появилось следующее
Расс называет это
И указатели на функции внутри itable (первое слово interface value) на самом деле имеют вид
Раздел спецификации про method expressions разъясняет:
Для метода с value-получателем существует также сигнатура с указателем:
Это как раз и гарантирует, что мы можем вызвать метод, определенный с value receiver даже для указателя — компилятор возьмет значение и вызовет нужную функцию.
Четвертый сценарий невозможен, так как множество методов для типа
Если подытожить: вся магия в том, что из 4 возможных комбинаций
Это, конечно, все занудство и, очень вероятно, где-то выше я исказил то, что реально написано в спецификации и у Расса (прошу поправлять в комментариях, если это так).
В книге Go101 в разделе про методы про это тоже написано, но используется терминология, которой нет в спецификации и официальных блог-постах (method normalization, boxing/unboxing), а это немного смущает, хотя очень впечатляет подробность.
Заранее спасибо, если укажете на заблуждения, ошибки, неточности и другие интересные ресурсы :)
Читал вчера статью Russ Cox об интерфейсах. Использую несовершенную форму глагола, потому что, несмотря на понимание в общих чертах, не могу сказать, что усвоил написанное (когда-нибудь придется сделать перевод-пересказ, чтобы проверить своё понимание).
Споткнулся, к своему сожалению, достаточно рано (см. изображение).
Когда речь зашла о списке указателей на функции, появилось следующее
method expression (согласно спецификации): (*Binary).String. Расс называет это
function pointer. В Go функции — первоклассные граждане и референс-типы, поэтому явный указатель не нужен. To call s.String(), the Go compiler generates code that does the equivalent of the C expression s.tab->fun[0](s.data): it calls the appropriate function pointer from the itable, passing the interface value's data word as the function's first (in this example, only) argument.Суть написанного в том, что при вызове нужного метода передается не само значение внутри интерфейса, а второе слово interface value — то есть, указатель на него.
И указатели на функции внутри itable (первое слово interface value) на самом деле имеют вид
(*Binary).String. Раздел спецификации про method expressions разъясняет:
type T struct {
a int
}
func (tv T) Mv(a int) int { return 0 } // value receiver
func (tp *T) Mp(f float32) float32 { return 1 } // pointer receiver
var t T
Вызов t.Mv(7) эквивалентен T.Mv(t, 7) и аналогично (&t).Mp(10) эквивалентен (*T).Mp(t, 10). Для метода с value-получателем существует также сигнатура с указателем:
func(tv *T, a int) int, в которой подразумевается indirection/dereference (то есть, разыменование) указателя и вызов: func(tv T, a int) int. Это как раз и гарантирует, что мы можем вызвать метод, определенный с value receiver даже для указателя — компилятор возьмет значение и вызовет нужную функцию.
Четвертый сценарий невозможен, так как множество методов для типа
T не включает в себя методы, определеленные для *T. Исключение: для обычных вызовов (неинтерфейсных) компилятор в состоянии добавить (&t). за нас. Это возможно, правда, только для типов, у которых можно взять адрес (addressable), например, у переменной. Если подытожить: вся магия в том, что из 4 возможных комбинаций
value/value, value/pointer, pointer/value, pointer/pointer существует 3 сигнатуры функции, которые позволяют подстроиться. Исключением является только случай, когда мы пытаемся вызвать метод с pointer-получателем, передавая value type. Это, конечно, все занудство и, очень вероятно, где-то выше я исказил то, что реально написано в спецификации и у Расса (прошу поправлять в комментариях, если это так).
В книге Go101 в разделе про методы про это тоже написано, но используется терминология, которой нет в спецификации и официальных блог-постах (method normalization, boxing/unboxing), а это немного смущает, хотя очень впечатляет подробность.
Заранее спасибо, если укажете на заблуждения, ошибки, неточности и другие интересные ресурсы :)
👍4🤔1
Hypothes.is
Небольшой оффтопик про чтение статей. Нашел прикольный инструмент, который позволяет делать аннотации и хайлайты в статьях и, что ещё более удобно, в PDF-файлах.
Очень актуально, когда нужно в чем-то разобраться, источников несколько (например, в случае выше — блог-пост, спецификация, ещё несколько статей) и понимание приходится складывать по кусочкам :)
Небольшой оффтопик про чтение статей. Нашел прикольный инструмент, который позволяет делать аннотации и хайлайты в статьях и, что ещё более удобно, в PDF-файлах.
Очень актуально, когда нужно в чем-то разобраться, источников несколько (например, в случае выше — блог-пост, спецификация, ещё несколько статей) и понимание приходится складывать по кусочкам :)
👍2
Go Time!
Go Time — классный подкаст, посвященный Go и всему, что с ним связано. Иногда приходят даже члены Go Team и участвуют в AMA (ask me anything) сессиях.
Один из самых интересных эпизодов — Creating the Go Programming Language с участием Роба Пайка и Роберта Гризмера.
Мне не так легко в плане концентрации даются длинные подкасты, но, к счастью, у Go Time для каждого эпизода есть транскрипт.
Например, эпизод про создание Go можно не слушать, а прочитать здесь.
Помимо прочего, это ещё и отличная возможность начать активно слушать об интересной для себя тематике на английском. Все непонятное и "нерасслышанное" можно подсмотреть в скрипте и разобрать, если неизвестен перевод или правильное произношение.
Уже за несколько эпизодов можно сильно поднять как свой "технический" английский, так и восприятие на слух — а это очень пригодится на собеседовании, например. В общем, win-win.
Приятного прослушивания и чтения :)
Go Time — классный подкаст, посвященный Go и всему, что с ним связано. Иногда приходят даже члены Go Team и участвуют в AMA (ask me anything) сессиях.
Один из самых интересных эпизодов — Creating the Go Programming Language с участием Роба Пайка и Роберта Гризмера.
Мне не так легко в плане концентрации даются длинные подкасты, но, к счастью, у Go Time для каждого эпизода есть транскрипт.
Например, эпизод про создание Go можно не слушать, а прочитать здесь.
Помимо прочего, это ещё и отличная возможность начать активно слушать об интересной для себя тематике на английском. Все непонятное и "нерасслышанное" можно подсмотреть в скрипте и разобрать, если неизвестен перевод или правильное произношение.
Уже за несколько эпизодов можно сильно поднять как свой "технический" английский, так и восприятие на слух — а это очень пригодится на собеседовании, например. В общем, win-win.
Приятного прослушивания и чтения :)