Pull to refresh
187
0
divan0 @divan0

Пользователь

Send message
Очень просто. Смотрите, вот даже на примере Go.

Объявление переменной типа T и типа «указатель на T»:
var foo T
var fooPtr *T = &foo

Паттерн понятен, теперь, на тип Т повесим метод Bar():
func (T) Bar() {}

Пока что всё логично. А теперь, как бы было бы «логично» вызывать этот метод для foo и fooPtr? Метод Bar ведь определен только для T, значит логично будет разыменовать fooPtr:
foo.Bar()
(*fooPtr).Bar()

Но это дополнительная нагрузка на программиста. Проще будет писать:
fooPtr.Bar()

а разыменование будет делать компилятор автоматически.

play.golang.org/p/hgcyQKW4-j

Это не так логично, но это плюс в сторону простоты. Если бы логичность была выше простоты, такого бы не было.
В последнее время на Хабре стало много публикаций на тему Rust и Go и достаточно мало про D. Главной причиной этого является поддержка этих языков Mozilla и Google, которые могут вкладывать большие деньги в свои детища.

Как человек, больше всего пишущий на Хабре про Go, заявляю, что Google не платит мне не копейки :) и само утверждение далеко от истины. Google платит зарплату разработчикам, ничего более. Всё остальное — результат естественного принятия языка миром. Все конференции, митапы, книги и прочая активность вокруг Go не имеют с Google никакой связи.
Ну да, выше речь шла про ресиверы и методы. А методы от функций отличаются лишь целесообразностью использования — метод подразумевает некоторый стейт, и операции с ним. А конструктор — это просто функция, которая создает новый объект, это безопасно для параллельного исполнения.
Про преждевременную оптимизацию — безусловно, верно. Но значения vs указатели — это не только про размеры. Например, если используется ресивер-значение, то этот метод автоматически безопасен для исполнения во многих горутинах. Если же ресивер — указатель, нужно думать о том, будет ли этот метод вызываться параллельно и будет ли меняться переменная-ресивер (и тогда уже защищать мьютексом).
Вот тут неплохо попытались расписать разные случаи: stackoverflow.com/questions/23542989/pointers-vs-values-in-parameters-and-return-values
хотя как понять насколько у меня «большущая структура»

Хороший вопрос. Как я понимаю, однозначного ответа на него нет, все попытки объяснить «насколько большой должна быть большая структура» сводились к простыням рассмотрения различных случаев. Но вот что написано в вики:
If the receiver is a large struct or array, a pointer receiver is more efficient. How large is large? Assume it's equivalent to passing all its elements as arguments to the method. If that feels too large, it's also too large for the receiver.

Если ресивер (метода) это большая структура или массиво, будет эффективнее использовать указатель. Насколько большая «большая структура»? Представьте, что вам нужно передать все её поля как параметры функции. Если это кажется слишком громоздким, значит это большая структура для ресивера.
Забавно, что ваш ход мыслей в статье упомянут :)
Да, чаще всего вы возвращаете указатель. Отчасти он «более популярен», потому что сложные структуры инициализируются с помощью new(), который возвращает именно указатель. В Effective Go это рассмотрено.

При этом ничего не мешает возвращать реальную структуру. Это может быть выгодней, в определенных случаях. Но тогда лучше не называть метод New..., чтобы избежать путаницы. Пример с image.Rect как раз об этом — можно спокойно возвращать не ссылку, называть это не New.., и все будет замечательно (хотя, конкретно по image я не знаю, почему решили так, а не иначе — но это однозначно не принципиальный вопрос, а каких-то мелких удобств в коде)
Отнюдь. Это отличная статья, которая получила заслуженное одобрение в англоязычном сегменте интернета. Лично я считаю её более чем интересной и познавательной.

И мне не сильно понятна ваша фамильярность. Помимо лично ваших «просьб писать» что-то, у меня есть собственные соображения о том, что писать и/или переводить, а также мнения других людей, кроме вас.
Я стараюсь тесты писать по мере написания кода. Если отложить «на потом», то. как правило, до них дело не дойдет. Тут же пример был несколько искусственный — фактически, переносил код с другой статьи. Подумал про тесты, но решил, что для статьи не релевантно. За что потом словил баг в комментариях и пожелал. :)
Я не очень понял проблему по описанию.
Могу посоветовать зайти к нам в слак- чат, и там спросить — будет продуктивнее :)
Ну тут и вправду незачем делать AboutSquare методом, правильней будет сделать функцию, принимающей параметр Figure.
Ну или определите AboutSquare для того типа, который встраивает, а не который встраивается (для RoundRectangle, в примере).
Оу! Вот это я лопухнулся! Спасибо, поправил. Вот еще думал, писать в «финальных правках» о надобности тестами покрыть, или нет )
package main

import (
	"math"
	"testing"
)

func TestCircle(t *testing.T) {
	square := NewCircle(0, 0, 10).Square()
	want := 100 * math.Pi
	if square != want {
		t.Fatalf("Want %v, but got %v", want, square)
	}
}
Согласен, спасибо за замечание. Старался сделать кальку с оригинального примера, но, и вправду, поправить эту оплошность ничего не стоит.
1) Обычно это не нужно «понимать», потому что это понимает компилятор — если переменная этого типа где-то используется как интерфейс (передается в функцию, принимающую интерфейс, или кастится к интерфейсу), то компилятор выдаст ошибку, если тип не реализует интерфейс. Вот прямо так и скажет:
cannot use T as MyIface… T does not implement MyIface (missing SomeMethod method)


Если же тип нигде и не используется как интерфейс, то, собственно, и надобности нет.
Теоретически, может быть специфическая ситуация, когда нужно все таки заставлять компилятор делать проверку (это может быть полезно в какой-то плагин-подобной архитектуре, например), то можно просто сделать кастинг к интерфейсу и этим гарантировать compile-time check:
var _ MyIface = (MyType)(nil)

Но я такой хак видел только в статьях, на реальном коде, пожалуй, и не видел.
Ну или тестами это можно «гарантировать».
Кстати, на смежную тему — есть утилита impl, которая позволяет быстро сгенерировать код функций-пустышек для нужного интерфейса.

2) в стандартной библиотеке — посмотрите всю папку encoding.
Я числа представляю обычно в виде циферной их записи — это никак не идёт под раздел «конкретный аудио-визуальный образ»

В моем понимании, идет. Когда вы оперируете числами, у вас возбуждаются определенные группы нейронов в визуальной и слуховой коре — а это и есть «аудиовизуальные образы».
А «понятия», как, по-вашему, в мозгу представлены?
Разные люди оперируют с числами (и вообще абстракциями) по-разному

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

Я нередко слышу от гоферов, что они выбрали Go просто потому что быстро позволил писать крутой софт. Если завтра появится ещё более удачное решение, которое будет более практично и будет позволять более быстрее делать такой же качественный результат — не моргнув глазом, перейдут с Го на него. Я и сам абсолютно такого же мнения. И это то, что я называю «практиками».

А «теоретики» (в моей терминологии) — строят какую-то искусственную систему координат, в которую вписывают инструменты, и судят с пеной у рта о языках по ней, часто на много-много лет закрывая себя только в рамках одного языка.

Хотя, возможно, моя терминология не сильно удачная, и можно лучше придумать. Но, я надеюсь, понятно, что в этой модели нет никаких проблем, что языки вроде Хаскеля реально используются в реальных проектах — если это практично (например, команда знает очень хорошо только хаскель — почему нет?), то это хороший выбор.
Спасибо за подробности, не знал.

Information

Rating
Does not participate
Location
Barcelona, Barcelona, Испания
Date of birth
Registered
Activity