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

В чем разница функций и методов в Go?

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

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

4b9b3361

Ответ 1

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

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

Термин "метод" придумал объектно-ориентированное программирование. На языке OOP (например, С++) вы можете определить "класс", который инкапсулирует данные и функции, которые принадлежат друг другу. Эти функции внутри класса называются "методами", и вам нужен экземпляр этого класса для вызова такого метода.

В 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)

Ответ 2

Ответ на Tux велик, но я хочу увеличить его с помощью методов Go с помощью struct (потому что именно там я использовал его часто). Поэтому предположим, что вы хотите построить что-то, чтобы рассчитать различные методы на треугольниках. Вы начинаете с 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
}

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

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

Ответ 3

Здесь подробно объясняются - 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)

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

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

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", когда метод фактически модифицирует значение, на которое указывает получатель, а не на его копию.