В чем разница функций и методов в Go? - PullRequest
43 голосов
/ 25 ноября 2011

Я пытаюсь начать работу с Go, и документация очень хороша.Что я не нашел в документации, так это различие между функциями и методами.

Насколько я понимаю на данный момент: функции являются "глобальными", что означает, что мне не нужно импортировать пакет для использования функций.они всегда там.Методы привязаны к пакетам.Это правильно?

Ответы [ 3 ]

79 голосов
/ 25 ноября 2011

Насколько я понимаю на данный момент: функции являются "глобальными", что означает, что мне не нужно импортировать пакет для использования функций, они всегда есть. Методы привязаны к пакетам. Это правильно?

Нет, это не правильно. Есть только пара функций из встроенного пакета , которые всегда доступны. Все остальное нужно импортировать.

Термин «метод» появился в объектно-ориентированном программировании. В языке ООП (например, C ++) вы можете определить «класс», который инкапсулирует данные и функции, которые принадлежат друг другу. Эти функции внутри класса называются «методами», и вам нужен экземпляр этого класса для вызова такого метода.

В Go терминология в основном та же, хотя Go не является языком ООП в классическом смысле. В Go функцию, которая принимает приемник, обычно называют методом (вероятно, только потому, что люди все еще привыкли к терминологии ООП).

Так, например:

func MyFunction(a, b int) int {
  return a + b
}
// Usage:
// MyFunction(1, 2)

но

type MyInteger int
func (a MyInteger) MyMethod(b int) int {
  return a + b
}
// Usage:
// var x MyInteger = 1
// x.MyMethod(2)
15 голосов
/ 22 ноября 2015

Ответ Тукса великолепен, но я хочу дополнить его с помощью методов Go с struct s (потому что именно здесь я часто его использовал). Итак, давайте предположим, что вы хотите построить что-то для вычисления различных методов на треугольниках. Вы начинаете с struct:

type Triangle struct {
    a, b, c float64
}

и затем вы хотели бы добавить некоторые функции для вычисления периметра и площади:

func valid(t *Triangle) error {
    if t.a + t.b > t.c && t.a + t.c > t.b && t.b + t.c > t.a {
        return nil
    }
    return errors.New("Triangle is not valid")
}

func perimeter(t *Triangle) (float64, error) {
    err := valid(t)
    if err != nil {
        return -1, err
    }

    return t.a + t.b + t.c, nil
}

func square(t *Triangle) (float64, error) {
    p, err := perimeter(t)
    if err != nil {
        return -1, err
    }

    p /= 2
    s := p * (p - t.a) * (p - t.b) * (p - t.c)
    return math.Sqrt(s), nil
}

А теперь у вас есть рабочая программа Go Playground . В этом случае ваша функция принимает параметр (указатель на треугольник) и что-то делает. В слове ООП люди могли создать класс, а затем добавить методы. Мы можем видеть нашу структуру как вид класса с полями, и теперь мы добавляем методы:

func (t *Triangle) valid() error {
    if t.a + t.b > t.c && t.a + t.c > t.b && t.b + t.c > t.a {
        return nil
    }
    return errors.New("Triangle is not valid")
}

func (t *Triangle) perimeter() (float64, error) {
    err := t.valid()
    if err != nil {
        return -1, err
    }

    return t.a + t.b + t.c, nil
}

func (t *Triangle) square() (float64, error) {
    p, err := t.perimeter()
    if err != nil {
        return -1, err
    }

    p /= 2
    s := p * (p - t.a) * (p - t.b) * (p - t.c)
    return math.Sqrt(s), nil
}

и у нас есть полностью рабочий пример .

Обратите внимание, что это действительно похоже на метод для объектов.

8 голосов
/ 01 февраля 2017

Они подробно объяснены здесь - https://anil.cloud/2017/01/26/golang-functions-methods-simplified/

Функция в Go следует синтаксису:

func FunctionName(Parameters...) ReturnTypes...

Пример:

func add(x int, y int) int

Выполнить:

  add(2,3) 

Метод похож на функцию, но привязан к типу (называемому как получатель). Официальное руководство гласит: «Метод - это функция со специальным аргументом получателя». Получатель появляется между ключевым словом func и именем метода. Синтаксис метода:

func (t ReceiverType) FunctionName(Parameters...) ReturnTypes...

Пример:

func (t MyType) add(int x, int y) int

Выполнить:

type MyType string
t1 := MyType("sample")
t1.add(1,2)

Теперь давайте добавим указатели в таблицу. Go lang - передача по значению, означает, что свежие копии параметров передаются в каждый вызов функции / метода. Чтобы передать их по ссылке, вы можете использовать указатели.

Синтаксис функции с указателем в списке аргументов / параметров.

func FunctionName(*Pointers...,Parameters...) ReturnTypes...

Пример

func add(t *MyType, x int, y int) int

Выполнить:

type MyType string
t1 := MyType("sample")
add(&t1,4,5)

Аналогично для методов тип получателя может быть указателем. Синтаксис метода с указателем (в качестве получателя)

func (*Pointer) FunctionName(Parameters...) ReturnTypes...

Пример * * одна тысяча тридцать шесть

func (t *MyType) add(x int, y int) int

Выполнить:

type MyType string
t1 := MyType("sample")
t1.add(2,3)

Обратите внимание, что мы все еще можем написать t1.add () для выполнения метода с получателем указателя (даже если «t1» не указатель), и Go будет интерпретировать его как (& t1) .add (). Точно так же метод с получателем значения может быть вызван с использованием указателя, Go будет интерпретировать p.add () как (* p) .add () в этом случае (где ‘p’ - указатель). Это применимо только для методов, а не для функций.

Методы с указателем-получателем очень полезны для получения поведения, подобного «Java», когда метод фактически изменяет значение, на которое указывает получатель, а не его копию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...