В чем разница функций и методов в Go?
Я пытаюсь начать работу с Go и документации. То, что я не нашел в документации, - это разница между функциями и методами.
Насколько я понимаю на данный момент: функции являются "глобальными", что означает, что мне не нужно импортировать пакет для использования функций, они всегда есть. Методы связаны с пакетами. Правильно ли это?
Ответы
Ответ 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", когда метод фактически модифицирует значение, на которое указывает получатель, а не на его копию.