목차
개요
go의 유형
基本类型
复合类型
数组
结构体
引用类型
그래서 go는 기본 유형이 일관되더라도 비교할 수 없습니다.
다음으로 다양한 유형의 비교가 가능한지 분석해 보겠습니다.
Array
구조
总结
백엔드 개발 Golang go에서 유형 비교 분석

go에서 유형 비교 분석

Jun 21, 2021 pm 04:09 PM
golang

다음 튜토리얼 칼럼인 golang에서는 go의 유형 비교 분석을 소개하겠습니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다!

개요

최근 인터뷰에서 면접관이 go의 유형 비교에 대해 질문한 바는 기본적으로 기초가 충분하지 않습니다. 인터넷에서 많은 정보를 읽고 제가 직접 간단한 요약도 해봤습니다. 하하!

go의 유형

먼저 go에 포함된 가장 기본적인 중앙 집중형 유형을 살펴보겠습니다

  • 기본 유형: Go의 가장 기본적인 유형에는 정수(int, uint, int8, uint8, int16, uint16, int32, uint32, int64, uint64, byte, rune 등), 부동 소수점 유형(float32, float64), 문자열(string도 a []rune 배열) 및 덜 일반적으로 사용되는 복합 유형(complex64/complex128). int、uint、int8、uint8、int16、uint16、int32、uint32、int64、uint64、byte、rune等)、浮点型(float32、float64)、字符串(string也是个[]rune数组)和比较不常用的复数类型(complex64/complex128)。
  • 复合类型:主要包括结构体数组
  • 引用类型:Slice、Map、Channel、指针
  • 接口类型:Error、io.Reader等

go作为强类型语言并不会和PHP等高级语言自动帮我们进行类型转换,所以我们在比较时必须用==两边的类型必须一致,即使他们底部类型一致也不行。看下面的代码

package main
import "fmt"
type A struct {
    Id int
}
type B struct {
    Id int
}
func main() {
    var a int
    var b int16
    // 编译报错:invalid operation a == b (mismatched types int and int16)
    fmt.Println(a == b)
    aStruct := A{Id:5}
    bStruct := B{Id:5}
    // 编译报错:invalid operation: aStruct == bStruct (mismatched types A and B)
    fmt.Println(aStruct == bStruct)
}
로그인 후 복사

所以go不会帮我们做隐式转换,即使底层的类型一致,也不能比较。
接下来我们从不同的类型来分析是否可以进行比较。

基本类型

go的基本类型就比较简单,只要类型是一样的,那么他们就是可以比较的,举个栗子:

package main
import "fmt"
func main() {
    var a int = 0
    var b int = 1
    // 输出false
    fmt.Println(a == b)
}
로그인 후 복사

不过基本类型中也要注意浮点型的比较就不像我们现实中的一样,比如0.1+0.2在计算中运行结果就不是0.3了,而是0.30000000000000004了

package main
import "fmt"

func main() {
    var a float64=0.1
    var b float64=0.2
    // 0.30000000000000004
    fmt.Println(a+b)
}
로그인 후 복사

为什么会这样,可以看下draveness(https://github.com/draveness) 大佬的这篇文章https://draveness.me/whys-the...

复合类型

数组

面试中也经常会问到go数组和切片的区别。数组在go中是必须先确定长度的,也就是长度不能再去扩容。并且它是个值拷贝,做参数传到一个函数中被修改,那么外部的值还是一样的不变的。Slice则相反。那么数组是否可以比较呢,看下面的例子:

package main
import "fmt"
func main() {
    a := [2]int{1, 2}
    b := [2]int{1, 2}
    c := [2]int{1, 3}
    d := [3]int{1, 2, 4}
    fmt.Println(a == b) // true
    fmt.Println(a == c) // false
    fmt.Println(a == d) // invalid operation: a == d (mismatched types [2]int and [3]int)
}
로그인 후 복사

可以看出,相同长度的数组是可以比较的,而不同长度的数组是不能进行比较的。原因是什么呢?这是因为数组类型中,数组的长度也是类型的一部分,不同长度的数组那么他们的类型也就被认为不同的,所以无法比较。

结构体

同样的Struct也是一样的。Struct的比较也从内部类型开始比较,每一类型的值相等才是相等的。如下例子:

package main
import "fmt"
type A struct {
    id int
    name string
}
func main() {
    a := A{id:5,name:"123"}
    b := A{id:5,name:"123"}
    c := A{id:5,name:"1234"}
    fmt.Println(a == b) // true
    fmt.Println(a == c) // false
}
로그인 후 복사

那么可以理解成Struct结构体是可以比较的吗。我们再来看个例子:

package main
import "fmt"
type A struct {
    id int
    name string
    son []int
}
func main() {
    a := A{id:5,name:"123",son:[]int{1,2,3}}
    b := A{id:5,name:"123",son:[]int{1,2,3}}
    fmt.Println(a == b) // invalid operation: a == b (struct containing []int cannot be compared)
}
로그인 후 복사

怎么又变成不可比较的呢?这就要看下面的引用类型了。

引用类型

上面中的例子结构体中带上切片就无法比较了,在go中SliceMap被定义成不能比较的类型。我们来看

如果Slice是可比较,那么用什么来定义是一样的切片呢?如果用地址,那么如果两个地址指向的Slice是一样的呢?这显然不合适。如果和数组一样的方式,那么我切片扩容了呢,就不相等了。所以长度和容量导致不好比较。虽然可以在语言层面解决这个问题,但是 golang 团队认为不值得为此耗费精力。所以Slice被当成不可比较。
同样的Map

복합 유형: 주로 구조배열을 포함합니다.

참조 유형: 슬라이스, 맵, 채널, 포인터.
  • 인터페이스 유형: 오류, io.Reader 등.
  • Go는 강력한 유형의 언어이므로 PHP와 같은 고급 언어로 유형 변환을 자동으로 수행하는 데 도움이 되지 않으므로 양쪽 유형을 비교할 때 ==를 사용해야 합니다. 하단 유형이 일관성이 있더라도 일관성을 유지하세요. 아래 코드를 보세요
package main
import "fmt"
type A struct {
    id int
    name string
}
func main() {
    a := &A { a : 1, b : "test1" }
    b := &A { a : 1, b : "test1" }
    c := a
    fmt.Println(a == b) // false
    fmt.Println(a == c) // true
    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)
    ch3 := ch1
    fmt.Println(ch1 == ch2) // false
    fmt.Println(ch1 == ch3) // true
}
로그인 후 복사

그래서 go는 기본 유형이 일관되더라도 비교할 수 없습니다.
다음으로 다양한 유형의 비교가 가능한지 분석해 보겠습니다.

기본 유형

🎜Go의 기본 유형은 유형이 동일하면 비교할 수 있습니다. 예: 🎜
type eface struct { // 16 字节
    _type *_type
    data  unsafe.Pointer
}

type iface struct { // 16 字节
    tab  *itab
    data unsafe.Pointer
}
로그인 후 복사
로그인 후 복사
🎜그러나 기본에서 부동 소수점 유형의 비교에도 주의해야 합니다. 우리와는 다릅니다. 현실도 마찬가지입니다. 예를 들어 0.1+0.2를 계산하면 결과가 0.3이 아니라 0.30000000000000004🎜
var a interface{} = 0
var b interface{} = 2
var c interface{} = 0
var d interface{} = 0.0
fmt.Println(a == b) // false
fmt.Println(a == c) // true
fmt.Println(a == d) // false
로그인 후 복사
로그인 후 복사
🎜이 글은 Draveness(https)에서 읽을 수 있습니다. //github.com/draveness) 글 https://draveness.me/whys-the...🎜🎜Composite type🎜

Array

🎜go 배열과 슬라이스의 차이점에 대해 인터뷰에서 자주 묻는 질문 . Go에서는 배열의 길이를 먼저 결정해야 합니다. 즉, 길이를 확장할 수 없습니다. 그리고 매개변수가 함수에 전달되어 수정되면 외부 값은 동일하게 유지됩니다. 슬라이스는 그 반대입니다. 따라서 배열을 비교할 수 있는지 여부는 다음 예를 참조하세요. 🎜
type A struct {
    a int
    b string
}

var a interface{} = A { a: 1, b: "test" }
var b interface{} = A { a: 1, b: "test" }
var c interface{} = A { a: 2, b: "test" }

fmt.Println(a == b) // true
fmt.Println(a == c) // false

var d interface{} = &A { a: 1, b: "test" }
var e interface{} = &A { a: 1, b: "test" }
fmt.Println(d == e) // false
로그인 후 복사
로그인 후 복사
🎜 같은 길이의 배열은 비교할 수 있지만 길이가 다른 배열은 비교할 수 없습니다를 알 수 있습니다. 이유는 무엇입니까? 이는 배열 유형에서는 배열의 길이도 유형의 일부이기 때문입니다. 길이가 다른 배열은 다른 유형으로 간주되므로 비교할 수 없습니다. 🎜

구조

🎜같은 구조는 같습니다. Struct의 비교도 내부 유형부터 시작되며, 각 유형의 값은 동일할 때만 동일합니다. 다음 예: 🎜
var a interface{} = []int{1, 2}
var b interface{} = []int{1, 2}
// panic: runtime error: comparing uncomparable type []int
fmt.Println(a == b)
로그인 후 복사
로그인 후 복사
🎜그래서 Struct 구조가 유사하다는 것을 이해할 수 있습니다. 또 다른 예를 살펴보겠습니다. 🎜
var f *os.File

var r io.Reader = f
var rc io.ReadCloser = f
fmt.Println(r == rc) // true

var w io.Writer = f
// invalid operation: r == w (mismatched types io.Reader and io.Writer)
fmt.Println(r == w)
로그인 후 복사
로그인 후 복사
🎜는 어떻게 다시 비교할 수 없게 되었나요? 이는 아래 참조 유형에 따라 다릅니다. 🎜🎜참조 유형🎜🎜위 예제 구조에는 슬라이스가 포함되어 있으면 비교할 수 없습니다. go에서는 SliceMap이 비교 불가능한 유형으로 정의되어 있습니다. 살펴보겠습니다🎜🎜슬라이스가 비교 가능한 경우 동일한 슬라이스를 정의하는 데 무엇이 사용됩니까? 주소를 사용하는 경우, 두 주소가 가리키는 Slice가 동일하다면 어떻게 될까요? 이는 분명히 부적절합니다. 배열과 동일하면 슬라이스를 확장하면 동일하지 않습니다. 따라서 길이와 용량을 비교하기가 어렵습니다. 이 문제는 언어 수준에서 해결될 수 있지만 golang 팀은 노력할 가치가 없다고 믿습니다. 따라서 Slice는 비교할 수 없는 것으로 간주됩니다.
동일한 Map도 비교할 수 없는 유형으로 정의됩니다. 그렇다면 참조 유형은 비교할 수 없는 것인가요? 아니요, 예를 살펴보세요. 🎜
type ReadCloser interface {
    Reader
    Closer
}
로그인 후 복사
로그인 후 복사
🎜참조 유형 변수는 특정 변수의 메모리 주소를 저장합니다. 따라서 참조 유형 변수를 비교하면 두 참조 유형이 동일한 변수를 저장하는지 여부가 결정됩니다. 🎜🎜🎜동일한 변수라면 메모리 주소도 동일해야 하고, 참조형 변수도 동일해야 하며, "=="를 사용하여 true로 판단하세요.🎜🎜동일한 변수라면 메모리 주소도 달라야 합니다. , "==" 결과는 false입니다🎜🎜🎜인터페이스 유형🎜🎜Go 언어는 인터페이스 유형에 메소드 세트가 포함되어 있는지 여부에 따라 인터페이스 유형을 두 가지 범주로 나눕니다.🎜
  • 使用 runtime.iface结构体表示包含方法的接口
  • 使用 runtime.eface结构体表示不包含任何方法的 interface{} 类型
type eface struct { // 16 字节
    _type *_type
    data  unsafe.Pointer
}

type iface struct { // 16 字节
    tab  *itab
    data unsafe.Pointer
}
로그인 후 복사
로그인 후 복사

所以我们可以得知,一个接口值是由两个部分组成的,即该接口对应的类型和接口对应具体的值。接口值的比较涉及这两部分的比较,只有当类型和值都相等(动态值使用==比较),两个接口值才是相等的。看个例子:

var a interface{} = 0
var b interface{} = 2
var c interface{} = 0
var d interface{} = 0.0
fmt.Println(a == b) // false
fmt.Println(a == c) // true
fmt.Println(a == d) // false
로그인 후 복사
로그인 후 복사

ac类型相同(都是int),值也相同(都是0,基本类型比较),故两者相等。 ab类型相同,值不等,故两者不等。 ad类型不同,aintdfloat64,故两者不等。

type A struct {
    a int
    b string
}

var a interface{} = A { a: 1, b: "test" }
var b interface{} = A { a: 1, b: "test" }
var c interface{} = A { a: 2, b: "test" }

fmt.Println(a == b) // true
fmt.Println(a == c) // false

var d interface{} = &A { a: 1, b: "test" }
var e interface{} = &A { a: 1, b: "test" }
fmt.Println(d == e) // false
로그인 후 복사
로그인 후 복사

ab类型相同(都是A),值也相同(结构体A),故两者相等。 ac类型相同,值不同,故两者不等。 de类型相同(都是*A),值使用指针(引用)类型的比较,由于不是指向同一个地址,故不等。

不过需要注意的是,如果接口中类型是切片或者Map不可比较的类型,那么会直接报错的。看个例子:

var a interface{} = []int{1, 2}
var b interface{} = []int{1, 2}
// panic: runtime error: comparing uncomparable type []int
fmt.Println(a == b)
로그인 후 복사
로그인 후 복사

ab的类型是切片类型,而切片类型不可比较,所以a == bpanic

接口值的比较不要求接口类型(注意不是动态类型)完全相同,只要一个接口可以转化为另一个就可以比较。例如:

var f *os.File

var r io.Reader = f
var rc io.ReadCloser = f
fmt.Println(r == rc) // true

var w io.Writer = f
// invalid operation: r == w (mismatched types io.Reader and io.Writer)
fmt.Println(r == w)
로그인 후 복사
로그인 후 복사

r的类型为io.Reader接口,rc的类型为io.ReadCloser接口。查看源码,io.ReadCloser的定义如下:

type ReadCloser interface {
    Reader
    Closer
}
로그인 후 복사
로그인 후 복사

io.ReadCloser可转化为io.Reader,故两者可比较。

io.Writer不可转化为io.Reader,编译报错。

总结

  • 可比较:int、ifloat、string、bool、complex、pointe、channel、interface、array
  • 不可比较:slice、map、function
  • 复合类型中如果带有不可比较的类型,那么该类型也是不可比较的。可以理解不可比较类型具有传递性。

위 내용은 go에서 유형 비교 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Golang을 사용하여 파일을 안전하게 읽고 쓰는 방법은 무엇입니까? Golang을 사용하여 파일을 안전하게 읽고 쓰는 방법은 무엇입니까? Jun 06, 2024 pm 05:14 PM

Go에서는 안전하게 파일을 읽고 쓰는 것이 중요합니다. 지침은 다음과 같습니다. 파일 권한 확인 지연을 사용하여 파일 닫기 파일 경로 유효성 검사 컨텍스트 시간 초과 사용 다음 지침을 따르면 데이터 보안과 애플리케이션의 견고성이 보장됩니다.

Golang 데이터베이스 연결을 위한 연결 풀을 구성하는 방법은 무엇입니까? Golang 데이터베이스 연결을 위한 연결 풀을 구성하는 방법은 무엇입니까? Jun 06, 2024 am 11:21 AM

Go 데이터베이스 연결을 위한 연결 풀링을 구성하는 방법은 무엇입니까? 데이터베이스 연결을 생성하려면 데이터베이스/sql 패키지의 DB 유형을 사용하고, 최대 동시 연결 수를 제어하려면 MaxIdleConns를 설정하고, 연결의 최대 수명 주기를 제어하려면 ConnMaxLifetime을 설정하세요.

golang 프레임워크의 장점과 단점 비교 golang 프레임워크의 장점과 단점 비교 Jun 05, 2024 pm 09:32 PM

Go 프레임워크는 높은 성능과 동시성 장점으로 인해 두각을 나타냅니다. 그러나 상대적으로 새로운 프레임워크, 작은 개발자 생태계, 일부 기능 부족 등 몇 가지 단점도 있습니다. 또한 빠른 변화와 학습 곡선은 프레임워크마다 다를 수 있습니다. Gin 프레임워크는 효율적인 라우팅, 내장된 JSON 지원 및 강력한 오류 처리로 인해 RESTful API를 구축하는 데 널리 사용됩니다.

Golang 프레임워크의 오류 처리에 대한 모범 사례는 무엇입니까? Golang 프레임워크의 오류 처리에 대한 모범 사례는 무엇입니까? Jun 05, 2024 pm 10:39 PM

모범 사례: 잘 정의된 오류 유형(오류 패키지)을 사용하여 사용자 정의 오류 생성 자세한 내용 제공 오류를 적절하게 기록 오류를 올바르게 전파하고 컨텍스트를 추가하기 위해 필요에 따라 오류를 숨기거나 억제하지 않음

JSON 데이터를 Golang의 데이터베이스에 저장하는 방법은 무엇입니까? JSON 데이터를 Golang의 데이터베이스에 저장하는 방법은 무엇입니까? Jun 06, 2024 am 11:24 AM

JSON 데이터는 gjson 라이브러리 또는 json.Unmarshal 함수를 사용하여 MySQL 데이터베이스에 저장할 수 있습니다. gjson 라이브러리는 JSON 필드를 구문 분석하는 편리한 방법을 제공하며, json.Unmarshal 함수에는 JSON 데이터를 비정렬화하기 위한 대상 유형 포인터가 필요합니다. 두 방법 모두 SQL 문을 준비하고 삽입 작업을 수행하여 데이터를 데이터베이스에 유지해야 합니다.

Golang 프레임워크 vs. Go 프레임워크: 내부 아키텍처와 외부 기능 비교 Golang 프레임워크 vs. Go 프레임워크: 내부 아키텍처와 외부 기능 비교 Jun 06, 2024 pm 12:37 PM

GoLang 프레임워크와 Go 프레임워크의 차이점은 내부 아키텍처와 외부 기능에 반영됩니다. GoLang 프레임워크는 Go 표준 라이브러리를 기반으로 하며 기능을 확장하는 반면, Go 프레임워크는 특정 목적을 달성하기 위해 독립적인 라이브러리로 구성됩니다. GoLang 프레임워크는 더 유연하고 Go 프레임워크는 사용하기 더 쉽습니다. GoLang 프레임워크는 성능 면에서 약간의 이점이 있고 Go 프레임워크는 확장성이 더 좋습니다. 사례: gin-gonic(Go 프레임워크)은 REST API를 구축하는 데 사용되고 Echo(GoLang 프레임워크)는 웹 애플리케이션을 구축하는 데 사용됩니다.

golang 프레임워크의 일반적인 보안 문제를 해결하는 방법은 무엇입니까? golang 프레임워크의 일반적인 보안 문제를 해결하는 방법은 무엇입니까? Jun 05, 2024 pm 10:38 PM

Go 프레임워크에서 일반적인 보안 문제를 해결하는 방법 웹 개발에서 Go 프레임워크가 널리 채택됨에 따라 보안을 보장하는 것이 중요해졌습니다. 다음은 샘플 코드를 통해 일반적인 보안 문제를 해결하기 위한 실용적인 가이드입니다. 1. SQL 주입 SQL 주입 공격을 방지하려면 준비된 문이나 매개변수화된 쿼리를 사용하세요. 예: constquery="SELECT*FROMusersWHEREusername=?"stmt,err:=db.Prepare(query)iferr!=nil{//Handleerror}err=stmt.QueryR

Golang 정규 표현식과 일치하는 첫 번째 하위 문자열을 찾는 방법은 무엇입니까? Golang 정규 표현식과 일치하는 첫 번째 하위 문자열을 찾는 방법은 무엇입니까? Jun 06, 2024 am 10:51 AM

FindStringSubmatch 함수는 정규 표현식과 일치하는 첫 번째 하위 문자열을 찾습니다. 이 함수는 일치하는 하위 문자열이 포함된 조각을 반환합니다. 첫 번째 요소는 전체 일치 문자열이고 후속 요소는 개별 하위 문자열입니다. 코드 예: regexp.FindStringSubmatch(text,pattern)는 일치하는 하위 문자열의 조각을 반환합니다. 실제 사례: 이메일 주소의 도메인 이름을 일치시키는 데 사용할 수 있습니다. 예를 들어 이메일:="user@example.com", 패턴:=@([^\s]+)$를 사용하여 도메인 이름 일치를 가져옵니다. [1].

See all articles