Подтвердить что ты не робот

Какие типы являются изменяемыми и неизменными на Google Go Language?

В Google Go я читал, что строки неизменяемы, нормально, но это int? Как насчет других типов? Как немного более старый программист, я предпочитаю изменчивость, хотя я знаю преимущества неизменности, я предпочитаю жить опасно.

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


Обновление, в чем меня больше всего беспокоят, - это практические проблемы в зависимости от того, какой тип является изменяемым или неизменным. Как и в типичном примере Java, если вы создаете String в цикле и цикле в 10 000 раз, вы получите 10000 строк, которые затем будут собраны в мусор. Это действительно было серьезной проблемой в проекте в компании, в которой я работал.

Возникает вопрос: неустойчивость Go в некоторых случаях вызывает ту же проблему?

Это влияет на то, как вы должны лечить var. (или я предполагаю, что это так).


Обновление снова, меня также беспокоят другие практические проблемы. Знание того, что что-то является неизменным, означает, что я могу писать код, который является параллельным, и обновление одной ссылки объекта не должно обновлять другие ссылки. Однако иногда я хочу делать опасные вещи, я хочу изменчивость.

Это последствия изменчивости против неизменности и влияют на то, как я могу написать код.

4b9b3361

Ответ 1

Не волнуйся - Иди, позволь тебе стрелять в ногу, если ты действительно хочешь: -)

Go не похож на Erlang, и это может быть то, с чем вы сталкиваетесь с вопросом.

x := 1
x = 2

выделяет одну переменную x со значением 1, затем переназначает ее на 2 - здесь не выделяется дополнительная память.

Как вы заметили, строки неизменяемы, поэтому выполнение строковых манипуляций может привести к созданию копий. Если вы обнаружите, что хотите сделать на месте изменения персональных данных, вы, вероятно, захотите использовать переменные []byte через пакет bytes.

Сообщение Russ Cox об этом должно ответить на большинство ваших вопросов об основных структурах данных: http://research.swtch.com/2009/11/go-data-structures.html

Как отмечали другие комментаторы, вам нужно посмотреть на семантику значений функций Go - они могут быть немного удивлены вначале.

Если у вас есть следующая функция:

func (t MyType) myFunc() {
    // do something to set a field in t
}

и вы вызываете в своем коде

myVar.myFunc()

вы можете быть удивлены, увидев, что это не делает то, что вы хотите, потому что t, который отображается в myFunc(), действительно является копией myVar.

Но будет работать следующее:

func (t *myType) myFunc() {
    // do something to set a field in t
}

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

Ответ 2

По моему мнению, сначала следует выделить следующие два понятия:

  • целые числа как математические объекты (то есть: значения)

  • переменные типа int

Тогда ответ: Целочисленные переменные являются изменяемыми, целые значения неизменяемы.

Это представление согласуется с спецификацией Go, которая гласит, что строки неизменяемы. Очевидно, что строковая переменная изменена.

Переменные (как понятие) в Go не менее:

  • названные переменные (такие как: var i int)
  • переменные, доступные через указатели

Объекты Mutable Go:

  • массивы и фрагменты
  • карты
  • Каналы
  • которые захватывают по крайней мере 1 переменную из внешней области

Неизменяемые объекты Go:

  • интерфейсы
  • booleans, числовые значения (включая значения типа int)
  • строки
  • Указатели
  • указатели на функции и замыкания, которые могут быть сведены к указателям на функции
  • структуры, имеющие одно поле

Объекты Go, которые некоторые люди могут считать изменчивыми, в то время как другие люди могут считать их неизменяемыми:

  • структуры, имеющие несколько полей

Ответ 3

Да, слово immutable появляется ровно один раз в Go spec. И это при обсуждении type string. Я думаю, вы должны смотреть на это больше из точек двойного просмотра Assignability и Адресуемость. Например, Go запретит вам переписывать переменную на другое значение типа с невыложенными свойствами, очевидно. Как и в С++ для классов, не предоставляющих конструктор копирования, но в Go Pimpl чувствует себя намного менее неудобно, подобает сообществу goroutines путем общения с философией.

Ответ 4

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

Для int нет смысла говорить о изменчивости, потому что, что такое "компоненты" int? Вы меняете int путем назначения целого нового int, но присваивание не считается "мутированием".

Существует некоторая связь между проблемами изменчивости и ссылочными или ценностными типами. Семантически, нет никакой разницы между неизменяемым ссылочным типом и типом значения. Зачем? Предположим, что int фактически был указателем на неизменяемый объект (т.е. *InternalIntObject без функций для изменения InternalIntObject). Когда вы назначаете такой указатель на переменную, он навсегда будет представлять одно и то же целочисленное значение (не может быть изменено другими, которые используют один и тот же объект), поскольку объект является неизменным. Это то же поведение, что и целочисленный тип значения. Вы можете назначить ints оператором присваивания; Аналогичным образом вы можете назначить эти указатели по заданию; результат будет таким же: назначенная переменная представляет то же самое целое число, что и назначенная. Единственным отличием было бы сравнение, и операторы арифметики должны были бы быть переопределены для удаления ссылки на указатель для вычисления результата.

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

В соответствии с тем, что вы просили, "изменяемые" типы обычно считаются ссылочными типами, кроме строки: карты, каналы, срезы (по отношению к данным, указанным срезом), а также указатели на что угодно (поскольку вы можете изменить значение в месте, на которое указывает указатель).

Ответ 5

Ваше беспокойство, похоже, больше связано с распределением, чем с неизменностью. Неизменность, безусловно, влияет на распределение, делая невозможным повторное использование памяти. Умный компилятор, возможно, может повторно использовать любую "неизменную" память, чей адрес, который он знает, не исчезает.

Помимо строк, будьте осторожны с интерфейсами. При назначении на интерфейс (при оптимизации в сторону) должно быть выделено больше размера слова. Кроме того, переменные, объявленные в теле цикла, чьи адреса удаляются, в том числе через замыкание, должны будут выделяться каждый раз через цикл. В противном случае назначение - это просто назначение. Значение просто копируется в память, представленную переменной.

Если вы используете make или new в цикле или любой литерал, который создает ссылку, распределение должно произойти (опять же, при оптимизации).

В принципе, все сводится к попытке повторного использования памяти, где вы можете, и надеяться, что компилятор сделает это за вас, когда вы не сможете, если это имеет смысл сделать это.

Ответ 6

Это дает мне один и тот же адрес каждый раз, поэтому, возможно, ints изменяемы.

package main

import "fmt"

func main() {
var i int
i = 5
fmt.Println(&i)
i = 6
fmt.Println(&i)
var k = 7
i = k
fmt.Println(&i)
}