내 연락처 정보
우편메소피아@프로톤메일.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
두 개의 정수와 부동 소수점 숫자의 크기를 각각 비교하는 함수를 작성하려면 두 개의 함수를 작성해야 합니다. 다음과 같이:
func Min(x, y float64) float64 {
if x < y {
return x
}
return y
}
func MinInt(x, y int) int {
if x < y {
return x
}
return y
}
두 함수는 데이터 유형이 다르다는 점을 제외하면 처리 논리가 완전히 동일합니다. 하나의 기능으로 위의 기능을 수행할 수 있는 방법이 있습니까? 네, 그건 일반적입니다.
func min[T int | float64](x, y T) T {
if x < y {
return x
}
return y
}
공식 웹사이트 문서:https://go.dev/blog/intro-generics
제네릭은 언어에 세 가지 중요한 새 기능을 추가합니다.
이제 함수와 유형에 유형 매개변수가 허용됩니다. 유형 매개변수 목록은 둥근 괄호 대신 대괄호를 사용한다는 점을 제외하면 일반 매개변수 목록과 유사합니다.
package main
import (
"fmt"
"golang.org/x/exp/constraints"
)
func GMin[T constraints.Ordered](x, y T) T {
if x < y {
return x
}
return y
}
func main() {
x := GMin[int](2, 3)
fmt.Println(x) // 输出结果为2
}
그중 Constraints.Ordered는 사용자 정의 유형입니다(소스 코드는 여기에 표시되지 않음).
이해가 되지 않는 경우 임시로 제약조건을 대체할 수 있습니다.int | float64
。
GMin에 유형 매개변수(이 경우 int)를 제공하는 것을 인스턴스화라고 합니다. 인스턴스화는 두 단계로 이루어집니다.
성공적인 인스턴스화 후에는 다른 함수처럼 호출할 수 있는 제네릭이 아닌 함수를 갖게 됩니다.예를 들어 다음과 같은 코드에서
fmin := GMin[float64]
m := fmin(2.71, 3.14)
모든 코드는
package main
import (
"fmt"
"golang.org/x/exp/constraints"
)
func GMin[T constraints.Ordered](x, y T) T {
if x < y {
return x
}
return y
}
func main() {
fmin := GMin[float64] // 相当于func GMin(x, y float64) float64{...}
m := fmin(2.71, 3.14)
fmt.Println(m) // 输出结果为2.71
}
GMin[float64]를 인스턴스화하면 실제로 함수 호출에 사용할 수 있는 원래의 부동 소수점 Min 함수가 생성됩니다.
유형 매개변수는 유형과 함께 사용될 수도 있습니다.
type Tree[T interface{}] struct {
left, right *Tree[T]
value T
}
func (t *Tree[T]) Lookup(x T) *Tree[T] { ... }
var stringTree Tree[string]
여기서 일반 유형 Tree는 유형 매개변수 T의 값을 저장합니다. 제네릭 유형에는 이 예의 Lookup과 같은 메서드가 있을 수 있습니다. 일반 유형을 사용하려면인스턴스화되어야 합니다.; Tree[string]은 유형 매개변수 string을 사용하여 Tree를 인스턴스화하는 예입니다.
유형 매개변수 목록의 각 유형 매개변수에는 유형이 있습니다. 유형 매개변수 자체가 유형이므로 유형 매개변수의 유형은 유형 세트를 정의합니다.이 메타타입은유형 제약。
일반 메소드 GMin에서는 유형 제약조건을 제약조건 패키지에서 가져옵니다. 정렬된 제약 조건은 정렬할 수 있는 값, 즉 < 연산자(또는 <=, > 등)와 비교할 수 있는 값을 갖는 모든 유형의 컬렉션을 설명합니다. 이 제약 조건은 정렬 가능한 값이 있는 유형만 GMin에 전달될 수 있도록 보장합니다. 이는 또한 GMin 함수 본문에서 이 유형 매개변수의 값을 < 연산자와 비교하는 데 사용할 수 있음을 의미합니다.
Go에서 유형 제약 조건은 인터페이스여야 합니다. . 즉, 인터페이스 유형을 값 유형 또는 메타 유형으로 사용할 수 있습니다. 인터페이스는 메소드를 정의하므로 특정 메소드가 있어야 하는 유형 제약 조건을 표현할 수 있습니다. 그러나 Constraints.Ordered도 인터페이스 유형이며 < 연산자는 메서드가 아닙니다.
인터페이스 유형의 이중 목적은 실제로 Go 언어에서 중요한 개념입니다. 예제 [1][2][3][4][5]를 통해 "인터페이스 유형은 값 유형 및 메타 유형으로 사용될 수 있습니다"라는 설명을 자세히 이해하고 설명하겠습니다.
인터페이스가 값 유형으로 사용되면 이러한 메소드를 구현하는 모든 유형을 인터페이스 변수에 할당할 수 있는 메소드 세트를 정의합니다. 이는 인터페이스의 가장 일반적인 사용입니다.
예를 들어:
type Stringer interface {
String() string
}
type Person struct {
Name string
}
func (p Person) String() string {
return p.Name
}
var s Stringer = Person{"Alice"} // Person 实现了 Stringer 接口
fmt.Println(s.String()) // 输出: Alice
이 예에서는Stringer
인터페이스는 값 유형으로 사용됩니다.Person
유형이 구현됩니다.String()
메서드에 할당할 수 있습니다.Stringer
유형 변수.
인터페이스가 메타 유형으로 사용되면 일반 프로그래밍에 사용할 유형 제약 조건 세트를 정의합니다. 이는 Go 1.18에 제네릭이 도입된 이후 새로운 사용법입니다.
예를 들어:
type Ordered interface {
int | float64 | string
}
func Min[T Ordered](a, b T) T {
if a < b {
return a
}
return b
}
fmt.Println(Min(3, 5)) // 输出: 3
fmt.Println(Min(3.14, 2.71)) // 输出: 2.71
fmt.Println(Min("a", "b")) // 输出: a
이 예에서는Ordered
인터페이스는 비교할 수 있는 유형(정수, 부동 소수점 숫자 및 문자열) 세트를 정의하는 메타 유형으로 사용됩니다.Min
함수는 이 인터페이스를 유형 제약 조건으로 사용하고 모든 것을 허용할 수 있습니다.Ordered
인수인 제약 조건 유형입니다.
이러한 이중 목적은 Go의 인터페이스를 일반 프로그래밍에 매우 강력하고 유연하게 만듭니다. 객체의 동작(값 유형)을 정의할 수 있을 뿐만 아니라 유형 컬렉션(메타 유형)도 정의할 수 있으므로 언어의 단순성을 유지하면서 코드의 표현력과 재사용성이 크게 향상됩니다.
최근까지 Go 사양에서는 인터페이스가 대략 인터페이스에 열거된 메서드 집합인 메서드 집합을 정의한다고 설명했습니다. 이러한 메서드를 모두 구현하는 모든 유형은 이 인터페이스를 구현합니다.
그러나 이것을 보는 또 다른 방법은 인터페이스가 유형 세트, 즉 이러한 메소드를 구현하는 유형을 정의한다고 말하는 것입니다. 이러한 관점에서 인터페이스 유형 집합의 요소인 모든 유형은 해당 인터페이스를 구현합니다.
두 보기 모두 동일한 결과로 이어집니다. 각 메소드 세트에 대해 이러한 메소드를 구현하는 해당 유형 세트, 즉 인터페이스에 의해 정의된 유형 세트를 상상할 수 있습니다.
그러나 우리의 목적에 따라 유형 집합 뷰는 메서드 집합 뷰에 비해 한 가지 장점이 있습니다. 컬렉션에 유형을 명시적으로 추가하여 새로운 방식으로 유형 집합을 제어할 수 있다는 것입니다.
이를 달성하기 위해 인터페이스 유형의 구문을 확장했습니다. 예를 들어, 인터페이스{ int|string|bool }은 int, string 및 bool 유형을 포함하는 유형 집합을 정의합니다.
다르게 말하면 인터페이스는 int, string 또는 bool로만 만족된다는 것입니다.
이제 Constraints.Ordered의 실제 정의를 살펴보겠습니다.
type Ordered interface {
Integer|Float|~string
}
이 선언은 Ordered 인터페이스가 모든 정수, 부동 소수점 및 문자열 유형의 컬렉션임을 나타냅니다. 수직 막대는 유형의 통합(또는 이 경우 유형 세트)을 나타냅니다. Integer 및 Float는 Constraints 패키지에 유사하게 정의된 인터페이스 유형입니다. Ordered 인터페이스는 어떤 메소드도 정의하지 않습니다.
유형 제약의 경우 일반적으로 문자열과 같은 특정 유형에 관심이 없습니다.이것은~
토큰의 목적.표현~string
기본 형식이 문자열인 모든 형식의 컬렉션을 나타냅니다.여기에는 유형 문자열 자체와 정의로 선언된 모든 유형이 포함됩니다.type MyString string
물론 우리는 여전히 인터페이스에서 메소드를 지정하고 이전 버전과 호환되기를 원합니다. Go 1.18에서 인터페이스는 이전과 마찬가지로 메서드와 내장된 인터페이스를 포함할 수 있지만, 비인터페이스 유형, 공용체 및 기본 유형 세트도 내장할 수 있습니다.
제약 조건으로 사용되는 인터페이스는 이름이 지정되거나(예: Ordered) 유형 매개변수 목록에 있는 리터럴 인터페이스 인라인일 수 있습니다. 예를 들어:
[S interface{~[]E}, E interface{}]
여기서 S는 슬라이스 유형이어야 하며 해당 요소 유형은 모든 유형이 될 수 있습니다.
이는 일반적인 상황이므로 위치를 제한하는 인터페이스의 경우 폐쇄형 인터페이스{}를 생략할 수 있으며 간단히 작성할 수 있습니다(Go 언어의 제네릭 구문 설탕 및 유형 제약 조건의 단순화된 작성).
[S ~[]E, E interface{}]
빈 인터페이스는 일반 Go 코드뿐만 아니라 유형 매개변수 목록에서도 일반적이므로 Go 1.18에서는 빈 인터페이스 유형의 별칭으로 미리 선언된 새로운 식별자 any를 도입합니다. 따라서 우리는 다음과 같은 관용적 코드를 얻습니다.
[S ~[]E, E any]
유형 매개변수를 사용하면 유형 매개변수를 전달해야 하며, 이는 장황한 코드로 이어질 수 있습니다. 일반 GMin 기능으로 돌아가서: