>  기사  >  백엔드 개발  >  Go는 해석된 언어인가요?

Go는 해석된 언어인가요?

青灯夜游
青灯夜游원래의
2021-03-16 11:08:135401검색

go는 해석된 언어입니다. Go(Golang이라고도 함)는 Google에서 개발한 가비지 수집 기능을 갖춘 정적으로 강력한 형식의 컴파일된 동시 프로그래밍 언어입니다. Go 언어의 장점: 쉬운 학습 곡선, 높은 개발 및 운영 효율성, 강력한 표준 라이브러리, 언어 수준에서 정의된 소스 코드 형식 지정 등

Go는 해석된 언어인가요?

이 튜토리얼의 운영 환경: windows10 시스템, GO 1.18, thinkpad t480 컴퓨터.

Go(Golang이라고도 함)는 Google의 Robert Griesemer, Rob Pike 및 Ken Thompson이 개발한 정적으로 강력한 형식의 컴파일 언어입니다.

Go의 구문은 C 언어에 가깝지만 변수 선언이 다릅니다. Go는 가비지 수집을 지원합니다. Go의 병렬 모델은 Tony Hall의 CSP(Communicating Sequential Process)를 기반으로 하며 유사한 모델을 채택한 다른 언어로는 Occam 및 Limbo가 있지만 채널 전송과 같은 Pi 작업 기능도 갖추고 있습니다. 플러그인 지원은 버전 1.8에서 시작됩니다. 이는 이제 일부 기능을 Go에서 동적으로 로드할 수 있음을 의미합니다.

C++에 비해 Go에는 열거형, 예외 처리, 상속, 제네릭, 어설션, 가상 함수 등과 같은 기능이 포함되어 있지 않지만 슬라이스 유형, 동시성, 파이프, 가비지 수집 및 인터페이스가 추가됩니다. 다른 기능의 경우. Go 2.0 버전은 제네릭을 지원하지만 단언문의 존재에 대해 부정적인 태도를 취하고 있으며 유형 상속을 제공하지 않는다고 방어합니다.

Java와 달리 Go에는 문자열 유형과 마찬가지로 연관 배열(해시 또는 사전이라고도 함)이 내장되어 있습니다.

Go 언어의 장점

Go는 배우기 쉽습니다

사실입니다. 프로그래밍 언어를 알고 있다면 "Go Language Tour"에서 몇 시간 동안 공부하면 Go를 마스터할 수 있습니다. 구문을 익히고 며칠 안에 첫 번째 실제 프로그램을 작성해 보세요. Practical Go 프로그래밍을 읽고 이해하고, 패키지 문서를 탐색하고, Gorilla 또는 Go Kit와 같은 웹 툴킷을 사용해 보십시오. 그러면 당신은 꽤 훌륭한 Go 개발자가 될 것입니다.

Go의 주요 목표는 단순성이기 때문입니다. Go를 배우기 시작했을 때 Java를 처음 발견한 것이 생각났습니다. 간단한 언어와 풍부하지만 부풀리지 않은 표준 라이브러리였습니다. 현재 Java가 많은 환경에 비해 Go를 배우는 것은 신선한 경험입니다. Go의 단순성으로 인해 Go 프로그램은 읽기가 매우 쉽지만 오류 처리로 인해 약간의 문제가 추가됩니다(자세한 내용은 아래 참조).

Go 언어의 단순성은 실수일 수 있습니다. Rob Pike의 말을 인용하면 단순함은 복잡하며 단순함 뒤에는 우리가 밟아야 할 많은 함정이 있다는 것을 알게 될 것입니다. 미니멀리즘은 우리가 DRY(Don't Repeat Yourself) 원칙을 위반하게 만들 것입니다.

고루틴과 채널을 기반으로 한 간단한 동시 프로그래밍

고루틴은 아마도 Go의 가장 큰 기능일 것입니다. 운영 체제 스레드와는 다른 경량 컴퓨팅 스레드입니다.

Go 프로그램이 I/O를 차단하는 것처럼 보이는 작업을 수행하면 Go 런타임은 실제로 goroutine을 일시 중지하고 이벤트가 결과를 사용할 수 있음을 나타낼 때 goroutine을 다시 시작합니다. 그 사이에 다른 고루틴도 실행될 예정입니다. 따라서 동기 프로그래밍 모델에서는 비동기 프로그래밍의 확장성 이점이 있습니다.

고루틴은 또한 가볍습니다. 스택은 수요에 따라 늘어나고 줄어들기 때문에 100개 또는 심지어 1000개의 고루틴을 갖는 것도 문제가 되지 않습니다.

이전 애플리케이션에는 고루틴 취약점이 있었습니다. 이 고루틴은 완료되기 전에 채널이 닫힐 때까지 기다리고 있었고 채널은 결코 닫히지 않았습니다(일반적인 교착 상태 문제). 이 프로세스는 이유 없이 CPU의 90%를 소모하며 expvars를 확인하면 600,000개의 유휴 고루틴이 표시됩니다. 고루틴 스케줄러가 CPU를 많이 사용하고 있는 것 같습니다.

물론, Akka와 같은 액터 시스템은 액터에 스택이 없기 때문에 수백만 명의 액터를 쉽게 처리할 수 있지만 대규모 동시 요청/응답 애플리케이션(예: http API)을 작성하기 위한 고루틴만큼 단순하지는 않습니다.

채널은 고루틴이 통신하는 방법입니다. 취약한 하위 수준 동기화 프리미티브에 의존하지 않고도 고루틴 간에 데이터를 보내고 받을 수 있는 편리한 프로그래밍 모델을 제공합니다. 채널에는 고유한 사용 패턴이 있습니다.

그러나 채널 크기가 잘못되면(기본적으로 버퍼링되지 않음) 교착 상태가 발생할 수 있으므로 채널을 신중하게 고려해야 합니다. 또한 채널을 사용해도 불변성이 없기 때문에 경쟁 조건이 방지되지 않는다는 점을 아래에서 확인할 수 있습니다.

풍부한 표준 라이브러리

Go의 표준 라이브러리는 특히 네트워크 프로토콜이나 API 개발과 관련된 모든 것(http 클라이언트 및 서버, 암호화, 아카이브 형식, 압축, 이메일 보내기 등)에 매우 풍부합니다. XSS 공격(Hugo에서 사용되는 것과 같은)을 자동으로 필터링하는 텍스트 및 html을 생성하는 html 파서와 상당히 강력한 템플릿 엔진도 있습니다.

다양한 API는 일반적으로 간단하고 이해하기 쉽습니다. 때로는 너무 단순해 보이기도 합니다. 이는 부분적으로는 고루틴 프로그래밍 모델이 "외견상 동기적인" 작업에만 신경 쓰면 된다는 것을 의미하기 때문입니다. 이는 최근에 시간 계산에 대해 알아낸 것처럼 일부 일반 함수가 많은 특수 함수를 대체할 수도 있기 때문입니다.

Go는 성능이 뛰어납니다

Go는 로컬 실행 파일로 컴파일됩니다. 많은 Go 사용자는 Python, Ruby 또는 Node.js 출신입니다. 이들에게는 서버가 처리할 수 있는 동시 요청 수가 크게 증가하는 것을 볼 수 있어 매우 흥미로운 경험입니다. 이는 동시 언어가 아니거나(Node.js) 전역 인터프리터 잠금이 있는 해석 언어를 사용하는 경우 실제로 매우 정상적인 현상입니다. 언어의 단순성과 결합되어 Go가 흥미로운 이유를 설명합니다.

Java와 비교하면 원시 성능 벤치마크에서는 그림이 그리 명확하지 않습니다. Go가 Java를 능가하는 부분은 메모리 사용량과 가비지 수집 분야입니다.

Go의 가비지 수집기는 대기 시간을 우선시하고 서버에서 특히 중요한 가동 중지 시간을 방지하도록 설계되었습니다. 이로 인해 CPU 비용이 높아질 수 있지만 수평 확장형 아키텍처에서는 머신을 더 추가하면 쉽게 해결됩니다. Go는 Google에서 설계했으며 리소스가 결코 부족하지 않습니다.

Go의 가비지 수집기(GC)는 Java에 비해 할 일이 적습니다. 슬라이스는 Java와 같은 포인터 배열이 아닌 연속 배열 구조입니다. 마찬가지로 Go 맵도 동일한 목적을 달성하기 위해 작은 배열을 버킷으로 사용합니다. 이는 가비지 수집기 작업이 줄어들고 CPU 캐시 지역화가 향상됨을 의미합니다.

Go는 또한 명령줄 유틸리티에서 Java에 비해 이점이 있습니다. 기본 실행 파일로서 Go 프로그램은 시작 오버헤드가 없는 반면 Java는 바이트 코드를 먼저 로드하고 컴파일해야 합니다.

언어 수준에서 소스 코드 형식 정의

제 경력에서 가장 열띤 논쟁 중 일부는 팀 내 코드 형식 정의를 둘러싸고 일어났습니다. Go는 코드의 표준 형식을 정의하여 이 문제를 해결합니다. gofmt 도구는 코드 형식을 다시 지정하며 옵션이 없습니다.

원하든 원하지 않든 gofmt는 코드 형식을 지정하는 방법을 정의하여 이 문제를 완전히 해결합니다.

표준화된 테스트 프레임워크

Go는 표준 라이브러리에서 우수한 테스트 프레임워크를 제공합니다. 병렬 테스트, 벤치마킹을 지원하고 네트워크 클라이언트와 서버를 쉽게 테스트할 수 있는 많은 유틸리티가 포함되어 있습니다.

Go 프로그램은 운영하기 쉽습니다

Python, Ruby 또는 Node.js에 비해 단일 실행 파일을 설치하는 것은 운영 및 유지 관리 엔지니어의 꿈입니다. Docker를 점점 더 많이 사용할수록 이 문제는 점점 줄어들지만 독립 실행형 실행 파일은 작은 Docker 이미지를 의미하기도 합니다.

Go에는 몇 가지 관찰 기능도 내장되어 있어 expvar 패키지를 사용하여 내부 상태와 지표를 게시하고 새 콘텐츠를 쉽게 추가할 수 있습니다. 그러나 기본 http 요청 핸들러에 자동으로 노출되어 보호되지 않으므로 주의하세요. Java에는 JMX와 유사한 기능이 있지만 훨씬 더 복잡합니다.

정리하는 것을 잊는 것을 방지하기 위한 Defer 문

defer 문의 목적은 Java의 finally와 유사합니다. 즉, 이 함수가 어떻게 종료되는지에 관계없이 현재 함수의 끝에서 일부 정리 코드를 실행합니다. defer의 흥미로운 점은 코드 블록과 아무런 관련이 없으며 언제든지 나타날 수 있다는 것입니다. 이렇게 하면 정리해야 하는 코드에 최대한 가깝게 정리 코드가 유지됩니다.

file, err := os.Open(fileName)
if err != nil {
    return
}
defer file.Close()
// 用文件资源的时候,我们再也不需要考虑何时关闭它

물론 Java의 평가판 리소스는 덜 장황하며 Rust는 소유자가 제거될 때 자동으로 리소스를 선언하지만 Go에서는 리소스 정리에 대해 명확하므로 리소스 할당에 가깝게 두는 것이 좋습니다.

새로운 유형

저는 짜증나고 두려운 것들이 있기 때문에 유형을 좋아합니다. 예를 들어 영구 객체 식별자를 문자열이나 긴 유형으로 전달합니다. 우리는 일반적으로 매개변수 이름에 id 유형을 인코딩하지만 이는 함수에 매개변수로 여러 식별자가 있고 일부 호출이 매개변수 순서와 일치하지 않는 경우 미묘한 버그를 생성합니다.

Go는 새로운 유형을 최고 수준으로 지원합니다. 즉, 해당 유형은 기존 유형이며 원래 유형과 다른 독립적인 ID가 부여됩니다. 패키징과 달리 새로운 유형에는 런타임 오버헤드가 없습니다. 이를 통해 컴파일러는 다음과 같은 종류의 오류를 포착할 수 있습니다.

type UserId string // <-- new type
type ProductId string
func AddProduct(userId UserId, productId ProductId) {}
func main() {
    userId := UserId("some-user-id")
    productId := ProductId("some-product-id")
    // 正确的顺序: 没有问题
    AddProduct(userId, productId)
    // 错误的顺序:将会编译错误 
    AddProduct(productId, userId)
    // 编译错误:
    // AddProduct 不能用 productId(type ProductId) 作为 type UserId的参数
    // Addproduct 不能用 userId(type UserId) 作为type ProfuctId 的参数 
}

불행하게도 제네릭이 부족하면 새로운 유형에 대한 작업이 번거로워집니다. 재사용 가능한 코드를 작성하려면 기본 유형의 값을 변환해야 하기 때문입니다.

더 많은 프로그래밍 관련 지식을 보려면 프로그래밍 비디오를 방문하세요! !

위 내용은 Go는 해석된 언어인가요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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