İçeriğe geç
academia.sh

Ders 16 / 16

C ile Birlikte Çalışma

Aynı iş iki yazımla karşılaştırılıyor — dilin kendi kodu ve cgo ile çağrılan bir C işlevi — ve ikisi de aynı ayırma sayısını (1) veriyor. Yerel çağrı içeren paket CGO_ENABLED=0 ile derlenmiyor, çapraz derlenmiyor ve kaçış çözümlemesinin C işlevinin gövdesine dair hiçbir bildirimi yok (0/21 satır). Sınırlayıcı ölçüm: C tarafında serbest bırakılmayan bir bellek ne çözümleyicide ne ayırma sayısında görünüyor — bedel çağrının kendisinde değil, aracın söyleyebildiklerinde. Kurs ve M09 Go müfredatı bu dersle, 16 satırlık bir tabloyla kapanıyor.

Yayın Güncelleme

Bu derste

  • Aynı işi yapan iki yazımı — dilin kendi kodu ve cgo ile çağrılan bir C işlevi — ayırma sayısıyla karşılaştırır
  • Yerel kütüphane çağrısı içeren bir paketin CGO_ENABLED=0 ile derlenebilirliğini ve çapraz derlenebilirliğini ölçer
  • Kaçış çözümlemesinin C işlevinin gövdesine dair hiçbir bildirim üretmediğini sayarak gösterir
  • Kursun ve M09 Go müfredatının kapanış tablosunu on beş kardeş dersten toplar
İçindekiler

Önceki ders bir çözümleyicinin temiz çıkmasının kusursuzluk anlamına gelmediğini, yalnız aradığı kalıbın bu kaynakta bulunmadığı anlamına geldiğini ölçtü — çözümleyicinin sessizliği aracın kural listesinin bir sınırıydı, bir kanıt değildi. Bu ders aynı sınırı bir adım öteye taşıyor: bir Go programı dilin sınırının dışına, başka bir dilin koduna çıktığında, o kod artık ne derleyicinin ne çözümleyicinin ne de profil aracının her zaman erişebildiği bir yerde duruyor. Sorulan soru dar: sınırı geçmenin bedeli hangi araçla, hangi sayıyla görünüyor?

C burada bir ürün ya da bir kütüphane kaydı değil, bir dil — adı yazılabilir, Go’nun kendisi gibi. Ama bu ders boyunca kullanılan düzenek, cgo, kursun geri kalanının taşımadığı bir bağımlılık taşıyor: kaynağın derlenebilmesi için gerçek bir C derleyicisinin ortamda bulunması ve CGO_ENABLED değişkeninin açık olması gerekiyor. DR19. Bu ders bu bağımlılığı açık bir varsayım olarak taşıyor; derleyici yoksa ya da CGO_ENABLED kapalıysa bloklar hiç derlenmiyor. Kursun on beş kardeş dersinin hiçbiri bu ikinci araç zincirine ihtiyaç duymadı.

cgo: Dilin Sınırını Aşan Çağrı

Standart kitaplık bu geçişi bir sözde paket üzerinden açıyor: import "C"’den hemen önce, boşluksuz yazılan bir yorum bloğu gerçek C kaynağı taşıyor, derleyici bu bloğu C derleyicisine geçirip sonucu Go tarafına bağlıyor. Aşağıdaki yerel.go, standart <string.h> ve <ctype.h> ile bir dizgiyi büyük harfe çeviren küçük bir C işlevi (buyukC) tanımlıyor ve iki Go sarmalayıcısından çağırıyor.

// yerel.go — C dilinde yazilmis bir islevi cgo ile cagiran yerel kutuphane sarmalayicisi
package main

/*
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

char* buyukC(const char* s) {
	size_t n = strlen(s);
	char* sonuc = (char*)malloc(n + 1);
	for (size_t i = 0; i < n; i++) {
		sonuc[i] = toupper((unsigned char)s[i]);
	}
	sonuc[n] = 0;
	return sonuc;
}
*/
import "C"
import "unsafe"

// buyukTemiz, dizgiyi C tarafindaki buyukC islevine gecirip sonucu geri aliyor;
// C tarafinda ayrilan sonuc arabellegini serbest birakiyor.
func buyukTemiz(s string) string {
	cs := C.CString(s)
	defer C.free(unsafe.Pointer(cs))
	sonuc := C.buyukC(cs)
	defer C.free(unsafe.Pointer(sonuc))
	return C.GoString(sonuc)
}

// buyukSizdiran ayni cagriyi yapiyor ama C tarafindaki sonuc arabellegini hic serbest birakmiyor.
func buyukSizdiran(s string) string {
	cs := C.CString(s)
	defer C.free(unsafe.Pointer(cs))
	sonuc := C.buyukC(cs)
	return C.GoString(sonuc)
}

C.CString verilen Go dizgisinin bir kopyasını C’nin kendi ayırıcısıyla (malloc) kuruyor — Go’nun çöp toplayıcısının hiç izlemediği bir bellek alanı. C.GoString ters yönde çalışıyor: C tarafındaki bir baytı okuyup Go’nun öbeğinde yeni bir dizgi kuruyor. buyukTemiz iki C arabelleğini de (cs, sonuc) C.free ile serbest bırakıyor; buyukSizdiran ikincisini hiç bırakmıyor — bu fark ilerleyen bir bölümde ölçülüyor.

Bu dersin geri kalanı, önceki derslerin paylaştığı iki yordamı aynen kullanıyor: paket geçici bir modül kuruyor, aracCalistir dilin kendi komutunu bu modül üzerinde çalıştırıyor.

// araclar.go — bu dersin paylastigi yardimcilar: gecici paket kurma, arac cagirma, bes kosum
package main

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"testing"
)

// goster bir bilgiyi, kimin soyledigini ve kanitini tek satirda yazdirir.
func goster(bilgi, soyleyen, kanit string) {
	fmt.Printf("%-40s %-7s %s\n", bilgi, soyleyen, kanit)
}

// paket, verilen dosyalari yeni bir gecici modulun icine yazar; yol hicbir yerde basilmaz.
func paket(dosyalar map[string]string) string {
	dizin, err := os.MkdirTemp("", "yerelkutuphane")
	if err != nil {
		return ""
	}
	os.WriteFile(filepath.Join(dizin, "go.mod"), []byte("module yereldeneme\n\ngo 1.24\n"), 0o644)
	for ad, icerik := range dosyalar {
		os.WriteFile(filepath.Join(dizin, ad), []byte(icerik), 0o644)
	}
	return dizin
}

// aracCalistir dilin kendi komutunu kosturur, cikisin basarili olup olmadigini doner; cikti basilmaz.
func aracCalistir(dizin string, ekOrtam []string, arg ...string) (string, bool) {
	cmd := exec.Command("go", arg...)
	cmd.Dir = dizin
	cmd.Env = append(append(os.Environ(), "GOTOOLCHAIN=local"), ekOrtam...)
	cikti, err := cmd.CombinedOutput()
	return string(cikti), err == nil
}

// besKosum ayni karsilastirmali olcumu bes kez kosturur; ilk deger ve kac ayri deger
// gorulduguyle doner. Kursun kararlilik kalibi: bir sayi ancak boyle kanitlanip yazilir.
func besKosum(f func(*testing.B)) (int64, int) {
	degerler := map[int64]bool{}
	var ilk int64
	for i := 0; i < 5; i++ {
		r := testing.Benchmark(f)
		degerler[r.AllocsPerOp()] = true
		if i == 0 {
			ilk = r.AllocsPerOp()
		}
	}
	return ilk, len(degerler)
}

Aynı İş, İki Yazım: Ayırma Sayısı

Kursun karşılaştırmalı ölçüm dersinde kurulan kalıp burada aynen sürüyor: aynı işin iki yazımı, beşer koşumda, yalnız ayırma sayısıyla karşılaştırılıyor. Bir yazım dilin kendi kodu (strings.ToUpper), öteki buyukTemiz üzerinden bir yerel kütüphane çağrısı.

// olcum1.go — ayni is iki yazimla: dilin kendi kodu ve yerel kutuphane cagrisi, ayirma sayisiyla karsilastiriliyor
package main

import (
	"fmt"
	"strings"
	"testing"
)

var ornekDizgi = "vida-somun-pul"
var yut string

//go:noinline
func benchGo(b *testing.B) {
	for i := 0; i < b.N; i++ {
		yut = strings.ToUpper(ornekDizgi)
	}
}

//go:noinline
func benchYerel(b *testing.B) {
	for i := 0; i < b.N; i++ {
		yut = buyukTemiz(ornekDizgi)
	}
}

func main() {
	fmt.Println("-- ayni is, iki yazim: ayirma sayisi --")
	goAyirma, goAyri := besKosum(benchGo)
	yerelAyirma, yerelAyri := besKosum(benchYerel)
	goster("dilin kendi kodu (strings.ToUpper)", "kosum", fmt.Sprint(goAyirma, " bes kosumda ayri deger=", goAyri))
	goster("yerel kutuphane cagrisi (cgo)", "kosum", fmt.Sprint(yerelAyirma, " bes kosumda ayri deger=", yerelAyri))
}
-- ayni is, iki yazim: ayirma sayisi --
dilin kendi kodu (strings.ToUpper)       kosum   1 bes kosumda ayri deger=1
yerel kutuphane cagrisi (cgo)            kosum   1 bes kosumda ayri deger=1

DR20. İki yazım da aynı sayıya, bire, ulaşıyor — ikisi de beş koşumda değişmiyor. Bu eşitlik yüzeyde “yerel çağrının bedeli yok” gibi okunabilir, ama buyukTemiz’in gövdesi strings.ToUpper‘ın yapmadığı iki işi de yapıyor: dizgiyi C’nin ayırıcısında bir kez kopyalıyor (CString), C tarafında ikinci bir arabellek ayırıp dolduruyor (buyukC), ikisini de free ile geri veriyor. Ayırma sayısındaki tek 1, yalnız GoString‘in Go öbeğine yazdığı son kopyayı sayıyor — C’nin malloc çağrıları bu sayıda hiç yok, çünkü ölçüm aracı yalnız kendi öbeğini izliyor. Bu gözlem ilerleyen bir bölümde tekrar ele alınıyor.

Yerel Çağrının Kaybettirdiği Araç Bilgisi

Kursun araç sınıfına yazdığı bilgiler — derlenebilirlik, çapraz derleme, derleyicinin kararı — bir yerel kütüphane çağrısı eklendiğinde ne kadarını taşıyor? Aşağıdaki ölçüm yerelKaynakı geçici bir modüle yazıp üç soru soruyor: CGO_ENABLED=0 ile derlenir mi, kopyası olmayan bir platforma (linux/arm64) çapraz derlenir mi ve kaçış bildirimlerinin kaçı Go tarafına, kaçı buyukC’ye dair.

// olcum2.go — yerel cagri iceren paketin kaybettirdigi arac bilgisi: derlenebilirlik, capraz derleme, kacis siniri
package main

import (
	"fmt"
	"os"
	"strings"
)

const yerelKaynak = "package main\n\n/*\n#include <string.h>\n#include <ctype.h>\n#include <stdlib.h>\n\nchar* buyukC(const char* s) {\n\tsize_t n = strlen(s);\n\tchar* sonuc = (char*)malloc(n + 1);\n\tfor (size_t i = 0; i < n; i++) sonuc[i] = toupper((unsigned char)s[i]);\n\tsonuc[n] = 0;\n\treturn sonuc;\n}\n*/\nimport \"C\"\nimport \"unsafe\"\n\nfunc buyukYerel(s string) string {\n\tcs := C.CString(s)\n\tdefer C.free(unsafe.Pointer(cs))\n\tsonuc := C.buyukC(cs)\n\tdefer C.free(unsafe.Pointer(sonuc))\n\treturn C.GoString(sonuc)\n}\n\nfunc main() {\n\t_ = buyukYerel(\"x\")\n}\n"

func main() {
	dizin := paket(map[string]string{"yerel.go": yerelKaynak})

	fmt.Println("-- yerel cagrinin kaybettirdigi arac bilgisi --")
	_, kapaliDerlendi := aracCalistir(dizin, []string{"CGO_ENABLED=0"}, "build", "-o", os.DevNull, ".")
	goster("CGO_ENABLED=0 ile derlendi mi", "arac", fmt.Sprint(kapaliDerlendi))

	_, caprazDerlendi := aracCalistir(dizin, []string{"CGO_ENABLED=1", "GOOS=linux", "GOARCH=arm64"}, "build", "-o", os.DevNull, ".")
	goster("linux/arm64 hedefinde derlendi mi", "arac", fmt.Sprint(caprazDerlendi))

	cikti, _ := aracCalistir(dizin, []string{"CGO_ENABLED=1"}, "build", "-gcflags=-m", "-o", os.DevNull, ".")
	satirlar := strings.Split(strings.TrimSpace(cikti), "\n")
	goTarafi := 0
	for _, s := range satirlar {
		if strings.Contains(s, "yerel.go") {
			goTarafi++
		}
	}
	cTarafi := strings.Count(cikti, "buyukC")
	goster("toplam kacis/derleme bildirimi satiri", "arac", fmt.Sprint(len(satirlar)))
	goster("yerel.go (go tarafi) satirina dair bildirim", "arac", fmt.Sprint(goTarafi))
	goster("buyukC govdesine (C tarafi) dair bildirim", "arac", fmt.Sprint(cTarafi))
}
-- yerel cagrinin kaybettirdigi arac bilgisi --
CGO_ENABLED=0 ile derlendi mi            arac    false
linux/arm64 hedefinde derlendi mi        arac    false
toplam kacis/derleme bildirimi satiri    arac    21
yerel.go (go tarafi) satirina dair bildirim arac    11
buyukC govdesine (C tarafi) dair bildirim arac    0

DR21. CGO_ENABLED=0 ile paket derlenmiyor, çünkü import "C" taşıyan bir dosya cgo kapalıyken derlemeye hiç girmiyor — Derleme Etiketleri dersinin “dosya derlemeden dışarıda kalıyor” davranışının bir başka biçimi, ama seçimi bir yorum satırı değil tek bir ortam değişkeni yapıyor. DR22. Çapraz Derleme dersi, platforma özgü çağrı taşımayan bir kaynağın üç hedefte de derlendiğini ölçmüştü; burada kopyası olmayan linux/arm64‘e derleme başarısız oluyor, çünkü artık gereken Go’nun çapraz derleyicisi değil, o hedefin kendi C derleyicisi ve bu ortamda yok.

DR23. Yirmi bir kaçış bildiriminin on biri yerel.go’daki bir satıra bağlanıyor. Bildirimlerin hiçbiri — sıfırı — buyukC‘nin adını taşımıyor. Bunun nedeni derleyicinin bu işlevi görmezden gelmesi değil, hiç görememesi: kaçış çözümlemesi Go’nun söz dizim ağacı üzerinde çalışan bir geçiş, buyukC’nin gövdesi ise C. Derleyici sınıra kadar (cs ve sonuc işaretçilerine) karar veriyor, ötesinde bir sorusu yok.

Sınırlayıcı Ölçüm: Bedel Çağrının Kendisinde Değil

Yukarıdaki ölçümler aynı yöne işaret ediyor: kaçış çözümlemesi sınırın ötesini görmüyor, derlenebilirlik bir C derleyicisine bağlı, ayırma sayısı yalnız Go’nun öbeğini sayıyor. Bu son ölçüm üçünü daha keskin bir örnekle birleştiriyor: buyukTemiz ile buyukSizdiran arasındaki tek fark, C tarafındaki sonuç arabelleğinin serbest bırakılıp bırakılmaması — gerçek bir sızıntı, C’nin kendi öbeğinde.

// sinir.go — sinirlayici olcum: bedel cagrinin kendisinde degil, aracin soyleyebildiklerinde
package main

import (
	"fmt"
	"testing"
)

const sizdiranKaynak = "package main\n\n/*\n#include <string.h>\n#include <ctype.h>\n#include <stdlib.h>\n\nchar* buyukC(const char* s) {\n\tsize_t n = strlen(s);\n\tchar* sonuc = (char*)malloc(n + 1);\n\tfor (size_t i = 0; i < n; i++) sonuc[i] = toupper((unsigned char)s[i]);\n\tsonuc[n] = 0;\n\treturn sonuc;\n}\n*/\nimport \"C\"\nimport \"unsafe\"\n\nfunc buyukSizdiran(s string) string {\n\tcs := C.CString(s)\n\tdefer C.free(unsafe.Pointer(cs))\n\tsonuc := C.buyukC(cs)\n\treturn C.GoString(sonuc)\n}\n\nfunc main() {\n\t_ = buyukSizdiran(\"x\")\n}\n"

var yut string
var ornekDizgi = "vida-somun-pul"

//go:noinline
func benchTemiz(b *testing.B) {
	for i := 0; i < b.N; i++ {
		yut = buyukTemiz(ornekDizgi)
	}
}

//go:noinline
func benchSizdiran(b *testing.B) {
	for i := 0; i < b.N; i++ {
		yut = buyukSizdiran(ornekDizgi)
	}
}

func main() {
	fmt.Println("-- sinirlayici olcum: bellek sizintisi kosumda gorunuyor mu --")
	temizAyirma, temizAyri := besKosum(benchTemiz)
	sizdiranAyirma, sizdiranAyri := besKosum(benchSizdiran)
	goster("serbest birakan yazimin ayirma sayisi", "kosum", fmt.Sprint(temizAyirma, " bes kosumda ayri deger=", temizAyri))
	goster("sizdiran yazimin ayirma sayisi", "kosum", fmt.Sprint(sizdiranAyirma, " bes kosumda ayri deger=", sizdiranAyri))

	dizin := paket(map[string]string{"yerel.go": sizdiranKaynak})
	_, temizMi := aracCalistir(dizin, []string{"CGO_ENABLED=1"}, "vet", "./...")
	goster("cozumleyici sizdiran yazimi da temiz buluyor mu", "arac", fmt.Sprint(temizMi))
}
-- sinirlayici olcum: bellek sizintisi kosumda gorunuyor mu --
serbest birakan yazimin ayirma sayisi    kosum   1 bes kosumda ayri deger=1
sizdiran yazimin ayirma sayisi           kosum   1 bes kosumda ayri deger=1
cozumleyici sizdiran yazimi da temiz buluyor mu arac    true

DR24. İki sayı birebir aynı — serbest bırakan da sızdıran da bir ayırma, beş koşumda tek değer. Ayırma sayısı yalnız Go öbeğini izlediği için, C tarafında büyüyen sızıntı hiç görünmüyor. Çözümleyici de aynı sessizliği veriyor: vet sızdıran yazımı da temiz buluyor, çünkü aradığı kalıplardan hiçbiri bir C çağrısının sonucunu serbest bırakmamayı kapsamıyor — zaten kapsayamaz, çünkü sızıntı buyukC’nin gövdesinde, Go söz diziminin dışında oluyor. Kursun ölçü ekseni burada kendi sınırına varıyor: üç yanıt da (kaynak, araç, koşum) bir sınırın içindeydi ve dışındaki C derleyicisinin kararlarına hiç ulaşmadı. Bedel çağrının kendisinde değil, aracın söyleyebildiklerinde: ne derleyici, ne çözümleyici, ne de profil aracı sınırın ötesindeki kodu görebiliyor.

Kurs Kapanışı

Bu kurs on altı ders boyunca tek bir soruyu sürdürdü: bir programa dair bir bilgiyi kim söylüyor — kaynak mı, araç mı, koşum mu? Ortak tanımın üç iddiası buna üç katman ekledi. Birincisi, bir programın hakkında bilinebileceklerin çoğu kaynakta yazılı değil: on bir bilginin yalnız ikisi metinde duruyor, geri kalan dokuzu bir araçtan ya da koşumdan geliyor. İkincisi, aracın söylediği ile koşumun söylediği aynı güvenilirlikte değil — araç bilgisi koşum gerektirmiyor, her çağrıda aynı yanıtı veriyor; koşum bilgisinin aynı kalıp kalmadığı ayrıca sınanmak zorunda. Üçüncüsü, kursa özgü olanı: karşılaştırmalı ölçümün iki sayısından yalnız biri, ayırma sayısı, tekrarlanabilir; süre hiçbir derste yazılmadı, basılmadı, ölçülmedi.

Bu son ders aynı üç sınıfı dilin sınırının ötesine taşıdı: kaçış çözümlemesi C işlevinin gövdesine dair bir şey söylemiyor, çözümleyici C’deki bir sızıntıyı görmüyor, ayırma sayısı C’nin ayırıcısını saymıyor. Kursun “araç söylüyor, doğru söylüyor demek değildir” okuması burada en keskin biçimine ulaşıyor: sınırın ötesinde araç ve koşum ikisi de susuyor ve bu susma kusursuzluk kanıtı değil, aracın hiç bakmadığı bir yerin kanıtı.

Kurs aşırı genelleme yapmadan kapanıyor: ölçülen tek bir yerel kütüphane çağrısıydı, cgo’nun bütün düzeneği değil; aynı sınır başka bir geçişte farklı bir araçla görünebilir. M09 Go müfredatı da bu dersle kapanıyor ve beş kursun beş sorusu aynı kökten çıkıyor: Go Temelleri yazılmayanın karşılığını sordu — tanımlı mı, reddedildi mi, açıkta mı; Arayüzler, Hatalar ve Genellikler bir davranışın tipe bağının nerede kurulduğunu sordu; Eşzamanlılık bir goroutine’in nasıl duracağını sordu; Standart Kütüphane ve Ağ Uygulamaları bir değerin sınırı geçerken tip bilgisine ne olduğunu sordu; bu kurs da bilginin hangi kaynaktan geldiğini sordu. Beşi de aynı gözlemde birleşiyor: bir programı yalnız kaynağını okuyarak bilmek yetmiyor.

Ders Ölçülen bilgi Söyleyen Sınırlayıcı ölçüm
Test Paketi Temelleri Testin geçip geçmediği koşum Geçen test sınadığının tuttuğunu söyler, doğruyu değil
Tablo Güdümlü Testler Vaka eklemenin kapsamayı değiştirip değiştirmediği koşum Altıncı vaka kapsamayı %100’de sabit bıraktı
HTTP Testleri İsteğin hangi durum koduna dönüştüğü koşum İstek adresi sabit bir blokta — sınanan ağ değil işleyici
Sahteleme ve Arayüz Ayrımı Sahtelemeyi mümkün kılan arayüz ayrımı kaynak Aşırı azaltmada gerçek reddetti, sahte kabul etti
Karşılaştırmalı Ölçüm On bir bilginin dağılımı, ayırma sayısı kaynak · araç · koşum (2/5/4) İş başına ile toplam ayırma ayrı, karışırsa yanıltır
Kapsam Raporlama Üç test kümesinin verdiği kapsama oranı koşum Denetlemeyen bir vaka hatalı kaynakla da %100 verdi
Profilleme İki çağrı biçiminin ayırma sayısı koşum Koşmayan dalın ayırdığı değer profilde görünmüyor
Kaçış Çözümlemesi Değerin yığıtta mı öbekte mi ayrıldığı kararı araç Karar dilin sözü değil, derleyicinin gerçekleştirim ayrıntısı
Çöp Toplama Davranışı Üç tekniğin ayırma sayısına etkisi koşum Aynı sayıya okunaklı ve okunaksız iki yazımla ulaşıldı
İzleme İki kurulumun olay sayısı koşum İz toplamak davranışı değiştirir, sayılar bu sınırla okunur
Derleme Etiketleri Hangi dosyaların derlemeye girdiği araç Dışarıdaki dosya silinmez, etiketlenene dek görülmez
Çapraz Derleme Kaynağın üç hedef için derlenip derlenmediği araç Derlenmek çalışacağı anlamına gelmez — varsayım hedefe bağlı
Bağlayıcı Seçenekleri Kaynaksız bir değerin ikiliye gömülmesi araç Bağlayıcı gömülen değeri doğrulamaz, boşu da kabul eder
Modül Yayımlama Sürümün imza düzeyinde uyumlu olup olmadığı kaynak · araç Aynı imza farklı sonuç verebilir, söz imzada davranışta değil
Statik Çözümleme ve Güvenlik Denetimi Farkın çözümleyicide yakalanıp yakalanmadığı araç Temiz çıkan kalıp koşunca çöktü — temizlik kusursuzluk değil
C ile Birlikte Çalışma Yerel çağrının ayırma sayısı, derlenebilirliği, kaçış görünürlüğü araç · koşum Sızan C belleği ne çözümleyicide ne ayırmada görünür

Özet

  • İki yazım — dilin kendi kodu, cgo ile çağrılan bir C işlevi — aynı ayırma sayısına (bir) ulaştı, ama bu eşitlik C tarafındaki iki malloc çağrısını hiç saymadı.
  • Yerel çağrı içeren bir paket CGO_ENABLED=0 ile derlenmedi, C derleyicisi bulunmayan bir hedefe çapraz derlenmedi; ders bu bağımlılığı açık bir varsayım olarak taşıdı.
  • Kaçış çözümlemesinin yirmi bir bildiriminin on biri Go tarafına bağlandı, sıfırı C işlevinin gövdesine — derleyici sınırın ötesini göremiyor, göz ardı etmiyor.
  • Sınırlayıcı ölçüm: serbest bırakılmayan C belleği ne çözümleyicide ne ayırma sayısında görünüyor; bedel çağrının kendisinde değil, aracın söyleyebildiklerinde.
  • M09 Go müfredatı bu dersle kapanıyor; beş kursun beş sorusu — yazılmayanın karşılığı, bağın yeri, goroutine’in durması, sınırda tip bilgisi, bu bilgiyi kim söylüyor — aynı gözlemde birleşiyor: bir programı bilmek, kaynağını okumaktan fazlasını gerektiriyor.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ ↵ Esc gezin · aç · kapat