ē®ę¬” ćÆććć« å¦ēæć®čęÆćØē°å¢ ćć£ć¬ćÆććŖę§é Cursor rules å¦ēæéå§ęć®ććć³ćć å¦ēæć®ęµć ć¹ć©ć¤ć¹ć®å
éØę§é ć«ć¤ć㦠ć¹ć©ć¤ć¹ć®å®¹éę”å¼µć¢ć«ć“ćŖćŗć ć«ć¤ć㦠čØē®éćØććć©ć¼ćć³ć¹ć®č¦ē¹ ć¹ć©ć¤ć¹ćčµ·ććć”ć¢ćŖćŖć¼ćÆ ęååć«ćććć”ć¢ćŖćŖć¼ćÆ å¤ę¬”å
ć¹ć©ć¤ć¹ć®ć«ć¼ćå¦ē ćć¹ćććę§é ä½ć®ć«ć¼ćå¦ē ć”ć¢ćŖćć¼ć«ć®ę“»ēØ ęę ćććć« åč ćÆććć« ććć«ć”ćÆć éēŗę¬éØéēŗ1éØćć¢ććéēŗéØęå±ć®åŗåø( @ktanonymous )ć§ćć ęčæćAI ćå©ēØć㦠Go ć®ć¹ć©ć¤ć¹ćć”ć¢ćŖćććć©ć¼ćć³ć¹ć«é¢ććå
容ćå¦ēæćć¦ćæćę©ä¼ćććć¾ććć ä»åćÆćć®éć®ä½éØć«ć¤ćć¦ć¾ćØćć¦ćæćććØęćć¾ćć ćŖććAI ć®åŗåć«é¢ćć¦ćÆåŗåå
容ććć®ć¾ć¾ä½æēØćć¦ććććäøéØčŖ¤ć£ć¦ććē®ęćććć¾ććć 飽ćć¾ć§ć対話ć®ćć°ćØćć¦åŗę¬ēć«ćÆę¹å¤ććć«čØč¼ćć¦ćć¾ćć čØäŗę¬ę㨠AI ć®åŗåć§å
容ćē°ćŖćå “åćÆčØäŗę¬ęć®å
容ćåŖå
ćć¦ćć ććć ć¾ććcursor ć®åÆ¾č©±ćéćć¦å¦ć°ćŖćć£ćććØć«ć¤ćć¦ćÆč§¦ććŖćć®ć§ć ćxxć«ćÆāÆāÆć使ćććććØęćććØćććććććć¾ććććäŗęæćć ććć å¦ēæć®čęÆćØē°å¢ ē®ē : å®å
Øć« AI äø»å°ć«ććå¦ēæä½éØćę¤čؼćć å©ēØć¢ćć« : claude-4-sonnet-thinking AI ćØćć£ćæ : Cursor ćć£ć¬ćÆććŖę§é /training āāā .cursor ā āāā rules ā āāā project_description.mdc āāā go_slice āāā compose.yml āāā docker ā āāā app āāā examples # ćµć³ćć«ć³ć¼ć āāā README.md āāā src āāā go.mod Cursor rules ā» å¦ēæćé²ććŖććę“ę°ććéØåćććć¾ć --- description: globs: alwaysApply: true --- # ćććøć§ćÆćę§ęć«ć¤ć㦠- ćć®ćććøć§ćÆććÆć¦ć¼ć¶ć¼ćå¦ēæć®ććć«å©ēØćć¾ćć ## ćć£ć¬ćÆććŖę§ęć«ć¤ć㦠- å¦ēæććé åććØć«ćć£ć¬ćÆććŖćä½ęćć¾ćć - å¦ēæē°å¢ćÆć³ć³ććē°å¢ć§å®č”ćć¾ćć - ćć£ć¬ćÆććŖå
ć®ćććć¬ćć«ć« ` compose.yml ` ćć ` docker ` ćć£ć¬ćÆććŖć«å½¹å²ććØć®ćć£ć¬ćÆććŖćä½ęć㦠` Dockerfile ` ćä½ęćć¦ćć ććć - ä¾ ```bash - react/ - compose.yml - docker - app - Dockerfile - db - Dockerfile - src ``` - åčę
å ±ć«é¢ćć¦ćÆćwebę¤ē“¢ćŖć©ć§ęę°ć®å
¬å¼ććć„ć”ć³ććåē
§ćć¦ćć ććć ## å¦ēæć®é²ćę¹ć«ć¤ć㦠- å¦ēæå
容ć®ę¬č³Ŗćčŗ«ć«ć¤ććććć«ćµć³ćć«ć¢ććŖć±ć¼ć·ć§ć³ćä½ęćć¾ć - å¦ēæćÆē°å¢ę§ēÆććå§ćć¾ć - å¦ēæå
容ćå®ēćććććć«ćå®č”ććć¹ćć³ćć³ććå®č£
ććć¹ćć³ć¼ćććÆć¤ćŗå½¢å¼ć«ćć¦ćć ćć - ćÆć¤ćŗć®åēć確čŖäŗé
ć«åƾććčæēćå¾
ććć«ę¬”ć®č©±ćé²ććŖćć§ćć ććć - å¦ēæć®ēµéć確čŖć§ććććć«ćåć¹ćććć§ä½ęćććµć³ćć«ć³ć¼ććÆåé¤ćććäøęøććććććŖćć§ćć ććć - å¦ēæćć¼ććÆä¼č©±ć®ćć³ć«åæ
ćęćåŗćć¦åæććŖćććć«ćć¦ćć ććć å¦ēæéå§ęć®ććć³ćć ## å¦ēæå
容 goć®ć¹ć©ć¤ć¹ćÆé
åć®ę ¹ę¬ēćŖä»ēµćæć«ć¤ćć¦ćē“°ććåä½ä»ę§ćęéļ¼ē©ŗéčØē®éćŖć©ć®č¦³ē¹ććę·±ęćććć§ć ## å¶é äøčØć®å¦ēæå
容ćÆä¼č©±ć®ęåć«åæ
ćęćåŗćć¦åæććŖćććć«ćć¦ćć ććć å¦ēæć®ęµć å¦ēæćÆä»„äøć®ćććŖć¹ćććć§é²ćæć¾ććć åŗę¬ēć«ćÆćåć¹ćććć§ćēćć®ę示 -> ćµć³ćć«ć³ć¼ćå®č£
-> ćÆć¤ćŗ -> č§£ēć»č§£čŖ¬ććē¹°ćčæćć¦ćć¾ćć ć¾ćććØć©ć¼ćŖć©ć§å¦ēæčŖä½ćč©°ć¾ćććØćÆćŖćć éäøć§ę°ć«ćŖć£ćå
容ć«é¢ćć¦ćÆčæ½å ć§ē¢ŗčŖććććØćć§ćć¾ććć ē°å¢ę§ēÆ ć¹ć©ć¤ć¹å
éØę§é čØē®éćØććć©ć¼ćć³ć¹ ć”ć¢ćŖćŖć¼ćÆ ęååć®åē
§åé” ę·±ććć¹ćęé©å ć”ć¢ćŖćć¼ć«ę“»ēØ ä»„éć§å®éć«å¦ćć å
容ć«ć¤ćć¦ę“ēćć¤ć¤ć å¦ēæć®ēµéćå
±ęććęå¾ć«ęęć«ć¤ćć¦ć¾ćØććććØęćć¾ćć ćŖććå®éć®ä½ę„㯠cursor ćęåć«ä½ć£ć¦ććć仄äøć®éēŗē°å¢ć§č”ćć¾ććć éēŗē°å¢ compose.yml services : go-slice-study : build : context : . dockerfile : ./docker/app/Dockerfile container_name : go-slice-study volumes : - ./src:/app/src - ./examples:/app/examples working_dir : /app stdin_open : true tty : true command : [ "sh" , "-c" , "tail -f /dev/null" ] docker/app/Dockerfile # ęę°ć®Goć®å
¬å¼ć¤ć”ć¼ćøćä½æēØ FROM golang:1.22-alpine # åæ
č¦ćŖćć¼ć«ćć¤ć³ć¹ćć¼ć« RUN apk add --no-cache \ git \ bash \ curl \ build-base # ä½ę„ćć£ć¬ćÆććŖćčØå® WORKDIR /app # Go modulesćęå¹å ENV GO111MODULE=on # å¦ēæēØć®åŗę¬ē°å¢ć«ćÆäøč¦ćŖćć¼ć«ćć¹ććć # RUN go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest # ć¢ććŖć±ć¼ć·ć§ć³ēØć®ćć£ć¬ćÆććŖćä½ę RUN mkdir -p /app/src /app/examples # ććć©ć«ćć®ć·ć§ć«ćbashć«čØå® RUN echo ' export PS1="\[\033[01;32m\]go-slice-study\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]$ " ' >> ~/.bashrc CMD [ " bash " ] go.mod module go-slice-study go 1.22 require ( github.com/stretchr/testify v1.8.4 ) require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) ć¹ć©ć¤ć¹ć®å
éØę§é ć«ć¤ć㦠ćµć³ćć«1ļ¼å®č£
ļ¼å®č”ēµęļ¼ å®č£
package main import ( "fmt" "unsafe" ) // ć¹ć©ć¤ć¹ć®å
éØę§é ć蔨ē¾ććę§é ä½ // runtime/slice.goć§å®ē¾©ććć¦ćććć®ćØåć type SliceHeader struct { Data uintptr // é
åćøć®å
é č¦ē“ ć®ćć¤ć³ćæ Len int // ć¹ć©ć¤ć¹ć®é·ć Cap int // ć¹ć©ć¤ć¹ć®å®¹é } func main() { fmt.Println( "=== Goć¹ć©ć¤ć¹ć®å
éØę§é å¦ēæ === \n " ) // 1. ć¹ć©ć¤ć¹ćŖćć©ć«ć®ä½ę fmt.Println( "1. ć¹ć©ć¤ć¹ćŖćć©ć«ć®ä½ę" ) s1 := [] int { 1 , 2 , 3 , 4 , 5 } printSliceInfo( "s1" , s1) // 2. makeć使ć£ćä½ę fmt.Println( " \n 2. makeć使ć£ćä½ę" ) s2 := make ([] int , 3 , 5 ) // len=3, cap=5 printSliceInfo( "s2" , s2) // 3. ć¹ć©ć¤ć·ć³ć°ęä½ fmt.Println( " \n 3. ć¹ć©ć¤ć·ć³ć°ęä½" ) s3 := s1[ 1 : 4 ] // ć¤ć³ćććÆć¹1ćć3ć¾ć§ printSliceInfo( "s3 (s1[1:4])" , s3) // s1ćØs3ćåćé
åćåē
§ćć¦ććććØćē¢ŗčŖ fmt.Printf( "s1ćØs3ćåćé
åćåē
§: %t \n " , unsafe.Pointer (&s1[ 1 ]) == unsafe.Pointer (&s3[ 0 ])) // 4. appendęä½ć«ćć容éę”å¼µ fmt.Println( " \n 4. appendęä½ć«ćć容éę”å¼µ" ) s4 := [] int { 1 , 2 , 3 } printSliceInfo( "s4 (before append)" , s4) s4 = append (s4, 4 , 5 , 6 , 7 ) printSliceInfo( "s4 (after append)" , s4) // 5. 容éćč¶³ććŖćå “åć®åå²ćå½ć¦ fmt.Println( " \n 5. 容éćč¶³ććŖćå “åć®åå²ćå½ć¦" ) s5 := make ([] int , 3 , 3 ) // ęŗęÆć®ē¶ę
s5[ 0 ], s5[ 1 ], s5[ 2 ] = 10 , 20 , 30 printSliceInfo( "s5 (ęŗęÆē¶ę
)" , s5) oldPtr := unsafe.Pointer (&s5[ 0 ]) s5 = append (s5, 40 ) // åå²ćå½ć¦ćēŗē newPtr := unsafe.Pointer (&s5[ 0 ]) printSliceInfo( "s5 (appendå¾)" , s5) fmt.Printf( "é
åćåå²ćå½ć¦ććć: %t \n " , oldPtr != newPtr) } // ć¹ć©ć¤ć¹ć®č©³ē“°ę
å ±ćåŗåććé¢ę° func printSliceInfo(name string , s [] int ) { if len (s) == 0 { fmt.Printf( "%s: [], len=%d, cap=%d, ptr=nil \n " , name, len (s), cap (s)) return } header := (*SliceHeader)( unsafe.Pointer (&s)) fmt.Printf( "%s: %v, len=%d, cap=%d, ptr=0x%x \n " , name, s, len (s), cap (s), header.Data) } å®č”ēµę === Goć¹ć©ć¤ć¹ć®å
éØę§é å¦ēæ === 1. ć¹ć©ć¤ć¹ćŖćć©ć«ć®ä½ę s1: [1 2 3 4 5], len=5, cap=5, ptr=0x400007e030 2. makeć使ć£ćä½ę s2: [0 0 0], len=3, cap=5, ptr=0x400007e060 3. ć¹ć©ć¤ć·ć³ć°ęä½ s3 (s1[1:4]): [2 3 4], len=3, cap=4, ptr=0x400007e038 s1ćØs3ćåćé
åćåē
§: true 4. appendęä½ć«ćć容éę”å¼µ s4 (before append): [1 2 3], len=3, cap=3, ptr=0x4000014078 s4 (after append): [1 2 3 4 5 6 7], len=7, cap=8, ptr=0x400010c000 5. 容éćč¶³ććŖćå “åć®åå²ćå½ć¦ s5 (ęŗęÆē¶ę
): [10 20 30], len=3, cap=3, ptr=0x4000014090 s5 (appendå¾): [10 20 30 40], len=4, cap=6, ptr=0x400007e090 é
åćåå²ćå½ć¦ććć: true ćÆć¤ćŗ1 ## **šÆ ćÆć¤ćŗē¬¬1å** ćµć³ćć«1ć®å®č”ēµęćč¦ć¦ć仄äøć®č³Ŗåć«ēćć¦ćć ććļ¼ **åé”**: ` s3 := s1[1:4] ` ć®ęä½ć§ć ` s3 ` ć®ćć¤ć³ćæå¤ć ` 0x40000b2038 ` ć«ćŖćć ` s1 ` ć®ćć¤ć³ćæå¤ ` 0x40000b2030 ` ćØćÆ8ćć¤ćļ¼0x8ļ¼ć®å·®ćććć¾ćć **ćŖć8ćć¤ćć®å·®ćććć®ć§ććććļ¼** ćć®å·®ć®ęå³ćØććććć¹ć©ć¤ć¹ć®ä»ēµćæćØé
åć®č¦ē“ åć«ć©ćé¢äæćć¦ćććčŖ¬ęćć¦ćć ććć **ćć³ć**: - ` s1 ` ć®å㯠` []int ` ć§ć - ` s3 ` 㯠` s1[1:4] ` ćć¤ć¾ć ` s1 ` ć®ć¤ć³ćććÆć¹1ććå§ć¾ćć¾ć - 64ćććć·ć¹ćć ć§ć® ` int ` ć®ćµć¤ćŗćčćć¦ćæć¦ćć ćć ććŖćć®åēććčćććć ććć ć¾ććé
ååē
§ćØćć¦ć®ć¹ć©ć¤ć¹ććä½ęććććć ć¹ć©ć¤ć·ć³ć°å¾ć®ćć¤ć³ćæå·®åćØåćµć¤ćŗć®é¢äæćę¤čؼćć¾ććć Go ć®ć¹ć©ć¤ć¹ćÆćé
åćęćåē
§ćć®ę§é ä½ć§ććć仄äøć® 3 č¦ē“ ććę§ęććć¾ć 1 2 ć ļ¼éØåļ¼é
åå
é ćęććć¤ć³ćæļ¼ptrļ¼ é·ćļ¼lenļ¼ å®¹éļ¼capļ¼ type slice struct { array unsafe.Pointer len int cap int } ä¾ćć°ć s := []int64{1, 2} ćØććć¹ć©ć¤ć¹ćććå “åć s[0] 㨠s[1] ć®ćć¤ć³ćæå¤ć®å·®å㯠64 bit = 8 Byte ćØćŖćć¾ćć ćµć³ćć«2ļ¼ćć¼ćæåćØć”ć¢ćŖć®é¢äæę§ćčæ½å ę¤čؼļ¼ļ¼å®č£
ļ¼å®č”ēµęļ¼ å®č£
package main import ( "fmt" "unsafe" ) func main() { fmt.Println( "=== 64ćććć·ć¹ćć ć§ć®intć®ćµć¤ćŗćØć”ć¢ćŖć¬ć¤ć¢ć¦ć === \n " ) // 1. ćć¼ćæåć®ćµć¤ćŗćē¢ŗčŖ fmt.Println( "1. ćć¼ćæåć®ćµć¤ćŗ" ) fmt.Printf( "int ć®ćµć¤ćŗ: %d ćć¤ć \n " , unsafe.Sizeof( int ( 0 ))) fmt.Printf( "int32 ć®ćµć¤ćŗ: %d ćć¤ć \n " , unsafe.Sizeof( int32 ( 0 ))) fmt.Printf( "int64 ć®ćµć¤ćŗ: %d ćć¤ć \n " , unsafe.Sizeof( int64 ( 0 ))) fmt.Printf( "byte ć®ćµć¤ćŗ: %d ćć¤ć \n " , unsafe.Sizeof( byte ( 0 ))) // 2. é
åå
ć§ć®č¦ē“ ć®é
ē½®ćē¢ŗčŖ fmt.Println( " \n 2. é
åå
ć§ć®č¦ē“ ć®é
ē½®" ) arr := [ 5 ] int { 10 , 20 , 30 , 40 , 50 } fmt.Println( "åč¦ē“ ć®ć”ć¢ćŖć¢ćć¬ć¹:" ) for i := 0 ; i < len (arr); i++ { fmt.Printf( "arr[%d] = %d, ć¢ćć¬ć¹: 0x%x \n " , i, arr[i], uintptr ( unsafe.Pointer (&arr[i]))) } // 3. ć¢ćć¬ć¹ć®å·®ćčØē® fmt.Println( " \n 3. é£ę„ććč¦ē“ éć®ć¢ćć¬ć¹å·®:" ) for i := 0 ; i < len (arr)- 1 ; i++ { addr1 := uintptr ( unsafe.Pointer (&arr[i])) addr2 := uintptr ( unsafe.Pointer (&arr[i+ 1 ])) diff := addr2 - addr1 fmt.Printf( "arr[%d]ćØarr[%d]ć®ć¢ćć¬ć¹å·®: %d ćć¤ć \n " , i, i+ 1 , diff) } // 4. ć¹ć©ć¤ć¹ć§ć®å®éć®ę¤čؼ fmt.Println( " \n 4. ć¹ć©ć¤ć¹ć§ć®å®éć®ę¤čؼ" ) s1 := [] int { 1 , 2 , 3 , 4 , 5 } s3 := s1[ 1 : 4 ] fmt.Printf( "s1ć®ćć¤ć³ćæ: 0x%x (č¦ē“ [0]ć®ć¢ćć¬ć¹) \n " , uintptr ( unsafe.Pointer (&s1[ 0 ]))) fmt.Printf( "s1[1]ć®ć¢ćć¬ć¹: 0x%x \n " , uintptr ( unsafe.Pointer (&s1[ 1 ]))) fmt.Printf( "s3ć®ćć¤ć³ćæ: 0x%x (č¦ē“ [0]ć®ć¢ćć¬ć¹) \n " , uintptr ( unsafe.Pointer (&s3[ 0 ]))) addr_s1_0 := uintptr ( unsafe.Pointer (&s1[ 0 ])) addr_s1_1 := uintptr ( unsafe.Pointer (&s1[ 1 ])) addr_s3_0 := uintptr ( unsafe.Pointer (&s3[ 0 ])) fmt.Printf( " \n s1[0]ćØs1[1]ć®ć¢ćć¬ć¹å·®: %d ćć¤ć \n " , addr_s1_1-addr_s1_0) fmt.Printf( "s1[1]ćØs3[0]ć®ć¢ćć¬ć¹: åćć? %t \n " , addr_s1_1 == addr_s3_0) // 5. ē°ćŖććć¼ćæåć§ć®ęÆč¼ fmt.Println( " \n 5. ē°ćŖććć¼ćæåć§ć®ęÆč¼" ) // byteé
åć®å “å byteArr := [ 5 ] byte { 1 , 2 , 3 , 4 , 5 } fmt.Println( "byteé
åć§ć®é£ę„č¦ē“ ć®ć¢ćć¬ć¹å·®:" ) for i := 0 ; i < len (byteArr)- 1 ; i++ { addr1 := uintptr ( unsafe.Pointer (&byteArr[i])) addr2 := uintptr ( unsafe.Pointer (&byteArr[i+ 1 ])) diff := addr2 - addr1 fmt.Printf( "byteArr[%d]ćØbyteArr[%d]ć®ć¢ćć¬ć¹å·®: %d ćć¤ć \n " , i, i+ 1 , diff) } // int32é
åć®å “å int32Arr := [ 5 ] int32 { 10 , 20 , 30 , 40 , 50 } fmt.Println( "int32é
åć§ć®é£ę„č¦ē“ ć®ć¢ćć¬ć¹å·®:" ) for i := 0 ; i < len (int32Arr)- 1 ; i++ { addr1 := uintptr ( unsafe.Pointer (&int32Arr[i])) addr2 := uintptr ( unsafe.Pointer (&int32Arr[i+ 1 ])) diff := addr2 - addr1 fmt.Printf( "int32Arr[%d]ćØint32Arr[%d]ć®ć¢ćć¬ć¹å·®: %d ćć¤ć \n " , i, i+ 1 , diff) } } å®č”ēµę === 64ćććć·ć¹ćć ć§ć®intć®ćµć¤ćŗćØć”ć¢ćŖć¬ć¤ć¢ć¦ć === 1. ćć¼ćæåć®ćµć¤ćŗ int ć®ćµć¤ćŗ: 8 ćć¤ć int32 ć®ćµć¤ćŗ: 4 ćć¤ć int64 ć®ćµć¤ćŗ: 8 ćć¤ć byte ć®ćµć¤ćŗ: 1 ćć¤ć 2. é
åå
ć§ć®č¦ē“ ć®é
ē½® åč¦ē“ ć®ć”ć¢ćŖć¢ćć¬ć¹: arr[0] = 10, ć¢ćć¬ć¹: 0x4000074cf8 arr[1] = 20, ć¢ćć¬ć¹: 0x4000074d00 arr[2] = 30, ć¢ćć¬ć¹: 0x4000074d08 arr[3] = 40, ć¢ćć¬ć¹: 0x4000074d10 arr[4] = 50, ć¢ćć¬ć¹: 0x4000074d18 3. é£ę„ććč¦ē“ éć®ć¢ćć¬ć¹å·®: arr[0]ćØarr[1]ć®ć¢ćć¬ć¹å·®: 8 ćć¤ć arr[1]ćØarr[2]ć®ć¢ćć¬ć¹å·®: 8 ćć¤ć arr[2]ćØarr[3]ć®ć¢ćć¬ć¹å·®: 8 ćć¤ć arr[3]ćØarr[4]ć®ć¢ćć¬ć¹å·®: 8 ćć¤ć 4. ć¹ć©ć¤ć¹ć§ć®å®éć®ę¤čؼ s1ć®ćć¤ć³ćæ: 0x4000074d30 (č¦ē“ [0]ć®ć¢ćć¬ć¹) s1[1]ć®ć¢ćć¬ć¹: 0x4000074d38 s3ć®ćć¤ć³ćæ: 0x4000074d38 (č¦ē“ [0]ć®ć¢ćć¬ć¹) s1[0]ćØs1[1]ć®ć¢ćć¬ć¹å·®: 8 ćć¤ć s1[1]ćØs3[0]ć®ć¢ćć¬ć¹: åćć? true 5. ē°ćŖććć¼ćæåć§ć®ęÆč¼ byteé
åć§ć®é£ę„č¦ē“ ć®ć¢ćć¬ć¹å·®: byteArr[0]ćØbyteArr[1]ć®ć¢ćć¬ć¹å·®: 1 ćć¤ć byteArr[1]ćØbyteArr[2]ć®ć¢ćć¬ć¹å·®: 1 ćć¤ć byteArr[2]ćØbyteArr[3]ć®ć¢ćć¬ć¹å·®: 1 ćć¤ć byteArr[3]ćØbyteArr[4]ć®ć¢ćć¬ć¹å·®: 1 ćć¤ć int32é
åć§ć®é£ę„č¦ē“ ć®ć¢ćć¬ć¹å·®: int32Arr[0]ćØint32Arr[1]ć®ć¢ćć¬ć¹å·®: 4 ćć¤ć int32Arr[1]ćØint32Arr[2]ć®ć¢ćć¬ć¹å·®: 4 ćć¤ć int32Arr[2]ćØint32Arr[3]ć®ć¢ćć¬ć¹å·®: 4 ćć¤ć int32Arr[3]ćØint32Arr[4]ć®ć¢ćć¬ć¹å·®: 4 ćć¤ć ć¹ć©ć¤ć¹ć®å®¹éę”å¼µć¢ć«ć“ćŖćŗć ć«ć¤ć㦠ćµć³ćć«3ļ¼å®č£
ļ¼å®č”ēµęļ¼ å®č£
package main import ( "fmt" ) func main() { fmt.Println( "=== Goć¹ć©ć¤ć¹ć®å®¹éę”å¼µć¢ć«ć“ćŖćŗć ę¤čؼ === \n " ) // 1. s4ć®ć±ć¼ć¹ćåē¾ć»åę fmt.Println( "1. s4ć®ć±ć¼ć¹åę: append(s4, 4, 5, 6, 7)" ) s4 := [] int { 1 , 2 , 3 } // len=3, cap=3 fmt.Printf( "s4 åęē¶ę
: len=%d, cap=%d \n " , len (s4), cap (s4)) fmt.Println( "- ē¾åØć®č¦ē“ ę°: 3" ) fmt.Println( "- čæ½å ććč¦ē“ ę°: 4å" ) fmt.Println( "- åæ
č¦ćŖåčØč¦ē“ ę°: 3 + 4 = 7" ) fmt.Println( "- 容éć2åć«ćććØ: 3 Ć 2 = 6" ) fmt.Println( "- åæ
č¦ćŖč¦ē“ ę°(7) > 2åć®å®¹é(6) ćŖć®ć§ć容éćÆ7仄äøćåæ
č¦" ) s4 = append (s4, 4 , 5 , 6 , 7 ) fmt.Printf( "s4 ę”å¼µå¾: len=%d, cap=%d \n " , len (s4), cap (s4)) fmt.Println( "ā ēµę: 7ćåæ
č¦ć ććå®éćÆ8ć«ćŖć£ć¦ććļ¼ć”ć¢ćŖć¢ć©ć¤ć”ć³ćļ¼" ) // 2. s5ć®ć±ć¼ć¹ćåē¾ć»åę fmt.Println( " \n 2. s5ć®ć±ć¼ć¹åę: append(s5, 40)" ) s5 := make ([] int , 3 , 3 ) // len=3, cap=3 s5[ 0 ], s5[ 1 ], s5[ 2 ] = 10 , 20 , 30 fmt.Printf( "s5 åęē¶ę
: len=%d, cap=%d \n " , len (s5), cap (s5)) fmt.Println( "- ē¾åØć®č¦ē“ ę°: 3" ) fmt.Println( "- čæ½å ććč¦ē“ ę°: 1å" ) fmt.Println( "- åæ
č¦ćŖåčØč¦ē“ ę°: 3 + 1 = 4" ) fmt.Println( "- 容éć2åć«ćććØ: 3 Ć 2 = 6" ) fmt.Println( "- åæ
č¦ćŖč¦ē“ ę°(4) < 2åć®å®¹é(6) ćŖć®ć§ć容éćÆ6ć«ćŖć" ) s5 = append (s5, 40 ) fmt.Printf( "s5 ę”å¼µå¾: len=%d, cap=%d \n " , len (s5), cap (s5)) fmt.Println( "ā ēµę: äŗę³éć6ć«ćŖć£ć¦ćć" ) // 3. Goć®å®¹éę”å¼µć«ć¼ć«ć®ę¤čؼ fmt.Println( " \n 3. Goć®å®¹éę”å¼µć«ć¼ć«:" ) fmt.Println( "ć¹ććć1: ę°ćć容éćę±ŗå®" ) fmt.Println( " - ē¾åØć®å®¹éć2åćć" ) fmt.Println( " - ććåæ
č¦ćŖč¦ē“ ę°ć2å容éćć大ćććć°ćåæ
č¦ćŖč¦ē“ ę°ćę”ēØ" ) fmt.Println( "ć¹ććć2: ć”ć¢ćŖć¢ć©ć¤ć”ć³ćčŖæę“" ) fmt.Println( " - CPUćØć”ć¢ćŖć®å¹ēåć®ćććē¹å®ć®ćµć¤ćŗć«čŖæę“ććć" ) // 4. ćć¾ćć¾ćŖććæć¼ć³ć§ć®ę¤čؼ fmt.Println( " \n 4. ćć¾ćć¾ćŖććæć¼ć³ć§ć®ę¤čؼ" ) testCases := [] struct { name string initialCap int appendCount int }{ { "1ć¤čæ½å " , 3 , 1 }, { "2ć¤čæ½å " , 3 , 2 }, { "3ć¤čæ½å " , 3 , 3 }, { "4ć¤čæ½å " , 3 , 4 }, { "5ć¤čæ½å " , 3 , 5 }, { "10ć¤čæ½å " , 3 , 10 }, } for _, tc := range testCases { s := make ([] int , tc.initialCap, tc.initialCap) fmt.Printf( " \n %s (åę容é:%d): \n " , tc.name, tc.initialCap) // čæ½å ććč¦ē“ ćęŗå toAppend := make ([] int , tc.appendCount) for i := range toAppend { toAppend[i] = 100 + i } fmt.Printf( " čæ½å å: len=%d, cap=%d \n " , len (s), cap (s)) fmt.Printf( " čæ½å č¦ē“ ę°: %d \n " , tc.appendCount) fmt.Printf( " åæ
č¦åčØč¦ē“ ę°: %d \n " , tc.initialCap+tc.appendCount) fmt.Printf( " 2å容é: %d \n " , tc.initialCap* 2 ) s = append (s, toAppend...) fmt.Printf( " ēµę: len=%d, cap=%d \n " , len (s), cap (s)) // äŗę³ćØå®éć®ęÆč¼ expected := tc.initialCap * 2 needed := tc.initialCap + tc.appendCount if needed > expected { fmt.Printf( " ā åæ
č¦ę°(%d) > 2å容é(%d) ćŖć®ć§ %d仄äøćåæ
č¦" , needed, expected, needed) } else { fmt.Printf( " ā åæ
č¦ę°(%d) ⤠2å容é(%d) ćŖć®ć§ %dåå¾" , needed, expected, expected) } fmt.Printf( " ā å®éćÆ%d \n " , cap (s)) } } å®č”ēµę === Goć¹ć©ć¤ć¹ć®å®¹éę”å¼µć¢ć«ć“ćŖćŗć ę¤čؼ === 1. s4ć®ć±ć¼ć¹åę: append(s4, 4, 5, 6, 7) s4 åęē¶ę
: len=3, cap=3 - ē¾åØć®č¦ē“ ę°: 3 - čæ½å ććč¦ē“ ę°: 4å - åæ
č¦ćŖåčØč¦ē“ ę°: 3 + 4 = 7 - 容éć2åć«ćććØ: 3 Ć 2 = 6 - åæ
č¦ćŖč¦ē“ ę°(7) > 2åć®å®¹é(6) ćŖć®ć§ć容éćÆ7仄äøćåæ
č¦ s4 ę”å¼µå¾: len=7, cap=8 ā ēµę: 7ćåæ
č¦ć ććå®éćÆ8ć«ćŖć£ć¦ććļ¼ć”ć¢ćŖć¢ć©ć¤ć”ć³ćļ¼ 2. s5ć®ć±ć¼ć¹åę: append(s5, 40) s5 åęē¶ę
: len=3, cap=3 - ē¾åØć®č¦ē“ ę°: 3 - čæ½å ććč¦ē“ ę°: 1å - åæ
č¦ćŖåčØč¦ē“ ę°: 3 + 1 = 4 - 容éć2åć«ćććØ: 3 Ć 2 = 6 - åæ
č¦ćŖč¦ē“ ę°(4) < 2åć®å®¹é(6) ćŖć®ć§ć容éćÆ6ć«ćŖć s5 ę”å¼µå¾: len=4, cap=6 ā ēµę: äŗę³éć6ć«ćŖć£ć¦ćć 3. Goć®å®¹éę”å¼µć«ć¼ć«: ć¹ććć1: ę°ćć容éćę±ŗå® - ē¾åØć®å®¹éć2åćć - ććåæ
č¦ćŖč¦ē“ ę°ć2å容éćć大ćććć°ćåæ
č¦ćŖč¦ē“ ę°ćę”ēØ ć¹ććć2: ć”ć¢ćŖć¢ć©ć¤ć”ć³ćčŖæę“ - CPUćØć”ć¢ćŖć®å¹ēåć®ćććē¹å®ć®ćµć¤ćŗć«čŖæę“ććć 4. ćć¾ćć¾ćŖććæć¼ć³ć§ć®ę¤čؼ 1ć¤čæ½å (åę容é:3): čæ½å å: len=3, cap=3 čæ½å č¦ē“ ę°: 1 åæ
č¦åčØč¦ē“ ę°: 4 2å容é: 6 ēµę: len=4, cap=6 ā åæ
č¦ę°(4) ⤠2å容é(6) ćŖć®ć§ 6åå¾ ā å®éćÆ6 2ć¤čæ½å (åę容é:3): čæ½å å: len=3, cap=3 čæ½å č¦ē“ ę°: 2 åæ
č¦åčØč¦ē“ ę°: 5 2å容é: 6 ēµę: len=5, cap=6 ā åæ
č¦ę°(5) ⤠2å容é(6) ćŖć®ć§ 6åå¾ ā å®éćÆ6 3ć¤čæ½å (åę容é:3): čæ½å å: len=3, cap=3 čæ½å č¦ē“ ę°: 3 åæ
č¦åčØč¦ē“ ę°: 6 2å容é: 6 ēµę: len=6, cap=6 ā åæ
č¦ę°(6) ⤠2å容é(6) ćŖć®ć§ 6åå¾ ā å®éćÆ6 4ć¤čæ½å (åę容é:3): čæ½å å: len=3, cap=3 čæ½å č¦ē“ ę°: 4 åæ
č¦åčØč¦ē“ ę°: 7 2å容é: 6 ēµę: len=7, cap=8 ā åæ
č¦ę°(7) > 2å容é(6) ćŖć®ć§ 7仄äøćåæ
č¦ ā å®éćÆ8 5ć¤čæ½å (åę容é:3): čæ½å å: len=3, cap=3 čæ½å č¦ē“ ę°: 5 åæ
č¦åčØč¦ē“ ę°: 8 2å容é: 6 ēµę: len=8, cap=8 ā åæ
č¦ę°(8) > 2å容é(6) ćŖć®ć§ 8仄äøćåæ
č¦ ā å®éćÆ8 10ć¤čæ½å (åę容é:3): čæ½å å: len=3, cap=3 čæ½å č¦ē“ ę°: 10 åæ
č¦åčØč¦ē“ ę°: 13 2å容é: 6 ēµę: len=13, cap=14 ā åæ
č¦ę°(13) > 2å容é(6) ćŖć®ć§ 13仄äøćåæ
č¦ ā å®éćÆ14 ćÆć¤ćŗ2 ## **šÆ ćÆć¤ćŗē¬¬2å** ꬔć®å¦ēæć¹ććććØćć¦ć**ć¹ć©ć¤ć¹ć®å®¹éę”å¼µć¢ć«ć“ćŖćŗć **ć«ć¤ćć¦ę·±ęććć¾ćććć **åé”**: ćµć³ćć«1ć®å®č”ć§ć ` s4 ` ć®å®¹éć ` 3ā8 ` ć ` s5 ` ć®å®¹éć ` 3ā6 ` ćØē°ćŖćęé·ććæć¼ć³ć示ćć¾ććć **ćŖćåćåę容é3ćŖć®ć«ćę”å¼µå¾ć®å®¹éćē°ćŖćć®ć§ććććļ¼** ćć³ćļ¼ - ` s4 ` 㯠` append(s4, 4, 5, 6, 7) ` ļ¼4ć¤ć®č¦ē“ ćčæ½å ļ¼ - ` s5 ` 㯠` append(s5, 40) ` ļ¼1ć¤ć®č¦ē“ ćčæ½å ļ¼ - Goć®å®¹éę”å¼µć¢ć«ć“ćŖćŗć ćčćć¦ćæć¦ćć ćć ććŖćć®ęØēććčćććć ććļ¼ ę¬”ć«ćć¹ć©ć¤ć¹ć®å®¹éę”å¼µć¢ć«ć“ćŖćŗć ć«ć¤ćć¦ę·±ęććć¾ććć ć¹ć©ć¤ć¹ć®ęć¤å®¹éćč¶
ćć¦č¦ē“ ćčæ½å ććććØććå “åćå
éØēć«å®¹éćę”å¼µććć¦ććć¾ćć ćć®ęćę”å¼µēć1.25ć2åēØåŗ¦ć«åć¾ćććć«å®¹éćę”å¼µćć¾ć 3 ć ć¾ćć詳瓰ćÆå²ęćć¾ćććęēµēćŖå®¹éćÆćµć¤ćŗćÆć©ć¹ 4 ćØćććć®ć«åŗć„ćć¦ę±ŗå®ććć¾ćć // nextslicecap computes the next appropriate slice length. func nextslicecap(newLen, oldCap int ) int { newcap := oldCap doublecap := newcap + newcap if newLen > doublecap { return newLen } const threshold = 256 if oldCap < threshold { return doublecap } for { // Transition from growing 2x for small slices // to growing 1.25x for large slices. This formula // gives a smooth-ish transition between the two. newcap += (newcap + 3 *threshold) >> 2 // We need to check `newcap >= newLen` and whether `newcap` overflowed. // newLen is guaranteed to be larger than zero, hence // when newcap overflows then `uint(newcap) > uint(newLen)`. // This allows to check for both with the same comparison. if uint (newcap) >= uint (newLen) { break } } // Set newcap to the requested cap when // the newcap calculation overflowed. if newcap <= 0 { return newLen } return newcap } čØē®éćØććć©ć¼ćć³ć¹ć®č¦ē¹ ćµć³ćć«4ļ¼å®č£
ļ¼å®č”ēµęļ¼ å®č£
package main import ( "fmt" "time" ) func main() { fmt.Println( "=== ć¹ć©ć¤ć¹ęä½ć®ęéć»ē©ŗéčØē®éåę === \n " ) // 1. appendęä½ć®åå“čØē®é fmt.Println( "1. appendęä½ć®åå“čØē®éåę" ) measureAppendPerformance() // 2. äŗå容éęå®ć®å¹ę fmt.Println( " \n 2. äŗå容éęå®ć®å¹ę" ) measurePreallocationEffect() // 3. ć¹ć©ć¤ć·ć³ć°ęä½ć®čØē®é fmt.Println( " \n 3. ć¹ć©ć¤ć·ć³ć°ęä½ć®čØē®é" ) measureSlicingPerformance() // 4. copyęä½ć®čØē®é fmt.Println( " \n 4. copyęä½ć®čØē®é" ) measureCopyPerformance() } // appendęä½ć®åå“čØē®éćęø¬å® func measureAppendPerformance() { sizes := [] int { 1000 , 10000 , 100000 , 1000000 } fmt.Println( "åēappendļ¼å®¹éęŖęå®ļ¼:" ) for _, size := range sizes { start := time.Now() var s [] int for i := 0 ; i < size; i++ { s = append (s, i) } duration := time.Since(start) fmt.Printf( " č¦ē“ ę° %7d: %v (1č¦ē“ ććć: %v) \n " , size, duration, duration/time.Duration(size)) } fmt.Println( " \n ēč«ēåę:" ) fmt.Println( " - åappendęä½: O(1) åå“ęé" ) fmt.Println( " - nåć®append: O(n) åčØęé" ) fmt.Println( " - 容éę”å¼µęć®ć³ćć¼: O(k) (kćÆē¾åØć®č¦ē“ ę°)" ) fmt.Println( " - ę”å¼µé »åŗ¦: log(n) åļ¼å®¹éćåć
ć§å¢å ļ¼" ) fmt.Println( " - åčØć³ćć¼ęé: O(n) (å¹¾ä½ē“ę°ć®å)" ) } // äŗå容éęå®ć®å¹ęćęø¬å® func measurePreallocationEffect() { size := 1000000 // 容éęŖęå® start := time.Now() var s1 [] int for i := 0 ; i < size; i++ { s1 = append (s1, i) } duration1 := time.Since(start) // 容éäŗåęå® start = time.Now() s2 := make ([] int , 0 , size) for i := 0 ; i < size; i++ { s2 = append (s2, i) } duration2 := time.Since(start) // ć¤ć³ćććÆć¹ē“ę„代å
„ start = time.Now() s3 := make ([] int , size) for i := 0 ; i < size; i++ { s3[i] = i } duration3 := time.Since(start) fmt.Printf( "č¦ē“ ę° %d ć§ć®ęÆč¼: \n " , size) fmt.Printf( " åēappend: %v \n " , duration1) fmt.Printf( " äŗå容é確äæ: %v (%.1fxéć) \n " , duration2, float64 (duration1)/ float64 (duration2)) fmt.Printf( " ē“ę„代å
„: %v (%.1fxéć) \n " , duration3, float64 (duration1)/ float64 (duration3)) fmt.Println( " \n ēč«ēåę:" ) fmt.Println( " - åēappend: O(n) + 容éę”å¼µć³ć¹ć" ) fmt.Println( " - äŗå容é確äæ: O(n) (容éę”å¼µćŖć)" ) fmt.Println( " - ē“ę„代å
„: O(n) (appendé¢ę°ć³ć¼ć«ćŖć¼ćć¼ććććŖć)" ) } // ć¹ć©ć¤ć·ć³ć°ęä½ć®čØē®éćęø¬å® func measureSlicingPerformance() { sizes := [] int { 1000 , 10000 , 100000 , 1000000 } fmt.Println( "ć¹ć©ć¤ć·ć³ć°ęä½:" ) for _, size := range sizes { // 大ććŖć¹ć©ć¤ć¹ćä½ę s := make ([] int , size) for i := range s { s[i] = i } start := time.Now() // ć¹ć©ć¤ć·ć³ć°ęä½ļ¼å¤ę°åå®č”ļ¼ iterations := 100000 for i := 0 ; i < iterations; i++ { _ = s[ 100 : size- 100 ] // ć¹ć©ć¤ć·ć³ć° } duration := time.Since(start) fmt.Printf( " å
ćµć¤ćŗ %7d: %v (1ęä½ććć: %v) \n " , size, duration, duration/time.Duration(iterations)) } fmt.Println( " \n ēč«ēåę:" ) fmt.Println( " - ć¹ć©ć¤ć·ć³ć°ęä½: O(1)" ) fmt.Println( " - ę°ććsliceę§é ä½ćä½ęććć ć" ) fmt.Println( " - å
ć®é
åćć³ćć¼ććŖć" ) fmt.Println( " - ćć¤ć³ćæćé·ćć容éć®čØē®ć®ćæ" ) } // copyęä½ć®čØē®éćęø¬å® func measureCopyPerformance() { sizes := [] int { 1000 , 10000 , 100000 , 1000000 } fmt.Println( "copyęä½:" ) for _, size := range sizes { src := make ([] int , size) dst := make ([] int , size) for i := range src { src[i] = i } start := time.Now() copy (dst, src) duration := time.Since(start) fmt.Printf( " č¦ē“ ę° %7d: %v (1č¦ē“ ććć: %v) \n " , size, duration, duration/time.Duration(size)) } fmt.Println( " \n ēč«ēåę:" ) fmt.Println( " - copyęä½: O(n) (nćÆć³ćć¼ććč¦ē“ ę°)" ) fmt.Println( " - ć”ć¢ćŖéć®ē·å½¢ć³ćć¼" ) fmt.Println( " - ćć¼ćć¦ć§ć¢ęé©åļ¼memmoveļ¼ć«ććé«é" ) } å®č”ēµę === ć¹ć©ć¤ć¹ęä½ć®ęéć»ē©ŗéčØē®éåę === 1. appendęä½ć®åå“čØē®éåę åēappendļ¼å®¹éęŖęå®ļ¼: č¦ē“ ę° 1000: 52.625µs (1č¦ē“ ććć: 52ns) č¦ē“ ę° 10000: 470.917µs (1č¦ē“ ććć: 47ns) č¦ē“ ę° 100000: 4.316875ms (1č¦ē“ ććć: 43ns) č¦ē“ ę° 1000000: 66.438667ms (1č¦ē“ ććć: 66ns) ēč«ēåę: - åappendęä½: O(1) åå“ęé - nåć®append: O(n) åčØęé - 容éę”å¼µęć®ć³ćć¼: O(k) (kćÆē¾åØć®č¦ē“ ę°) - ę”å¼µé »åŗ¦: log(n) åļ¼å®¹éćåć
ć§å¢å ļ¼ - åčØć³ćć¼ęé: O(n) (å¹¾ä½ē“ę°ć®å) 2. äŗå容éęå®ć®å¹ę č¦ē“ ę° 1000000 ć§ć®ęÆč¼: åēappend: 46.498333ms äŗå容é確äæ: 105.046542ms (0.4xéć) ē“ę„代å
„: 2.286375ms (20.3xéć) ēč«ēåę: - åēappend: O(n) + 容éę”å¼µć³ć¹ć - äŗå容é確äæ: O(n) (容éę”å¼µćŖć) - ē“ę„代å
„: O(n) (appendé¢ę°ć³ć¼ć«ćŖć¼ćć¼ććććŖć) 3. ć¹ć©ć¤ć·ć³ć°ęä½ć®čØē®é ć¹ć©ć¤ć·ć³ć°ęä½: å
ćµć¤ćŗ 1000: 96.375µs (1ęä½ććć: 0s) å
ćµć¤ćŗ 10000: 82.917µs (1ęä½ććć: 0s) å
ćµć¤ćŗ 100000: 123.167µs (1ęä½ććć: 1ns) å
ćµć¤ćŗ 1000000: 179.917µs (1ęä½ććć: 1ns) ēč«ēåę: - ć¹ć©ć¤ć·ć³ć°ęä½: O(1) - ę°ććsliceę§é ä½ćä½ęććć ć - å
ć®é
åćć³ćć¼ććŖć - ćć¤ć³ćæćé·ćć容éć®čØē®ć®ćæ 4. copyęä½ć®čØē®é copyęä½: č¦ē“ ę° 1000: 708ns (1č¦ē“ ććć: 0s) č¦ē“ ę° 10000: 14.791µs (1č¦ē“ ććć: 1ns) č¦ē“ ę° 100000: 220.584µs (1č¦ē“ ććć: 2ns) č¦ē“ ę° 1000000: 1.174583ms (1č¦ē“ ććć: 1ns) ēč«ēåę: - copyęä½: O(n) (nćÆć³ćć¼ććč¦ē“ ę°) - ć”ć¢ćŖéć®ē·å½¢ć³ćć¼ - ćć¼ćć¦ć§ć¢ęé©åļ¼memmoveļ¼ć«ććé«é ē¶ćć¦ćć¹ć©ć¤ć¹ć®ä½ęę¹ę³å„ć«å¦ēęéćčØęø¬ćććć©ć¼ćć³ć¹ęÆč¼ćå®ę½ćć¾ććć ćµć³ćć«4ćå®č”ććććØć§ćć¹ć©ć¤ć¹ć®ä½ęę¹ę³ć«ćć£ć¦ä»„äøć®ćććŖććć©ć¼ćć³ć¹ē¹ę§ććććØčććććććØć確čŖć§ćć¾ććć åęåę容éęå®ćŖćļ¼forć«ć¼ćć§append: O(n) + append ć³ć¼ć«ćŖć¼ćć¼ććć + 容éę”å¼µ åęåę容éęå®ććļ¼forć«ć¼ćć§append: O(n) + append ć³ć¼ć«ćŖć¼ćć¼ććć åęåę容éęå®ććļ¼forć«ć¼ćć§ć¤ć³ćććÆć¹ęå®ä»£å
„: O(n) ć¹ć©ć¤ć·ć³ć° ( s2 := s1[start:end] ): O(1) ćć¤ć³ćæćé·ćć容éćčØē®ćć¦ę°ćć slice ćä½ęććć ć copy : O(n) ļ¼ n ćÆć³ćć¼ććč¦ē“ ę°ļ¼ memmove ć«ććęé©åć§é«é ć”ć¢ćŖé åć«ä¾åļ¼å°ććć¹ć©ć¤ć¹ćÆéćć大ććć¹ć©ć¤ć¹ćÆé
ććŖćå¾åļ¼ ć¹ć©ć¤ć¹ćčµ·ććć”ć¢ćŖćŖć¼ćÆ ćµć³ćć«5ļ¼å®č£
ļ¼å®č”ēµęļ¼ å®č£
package main import ( "fmt" "runtime" "time" "unsafe" ) // ć°ćć¼ćć«å¤ę°ć§äæęććććØć§ćć¬ćć¼ćøć³ć¬ćÆć·ć§ć³ćé²ć var globalSlices [][] int // åé”ć®ććé¢ę°ļ¼å¤§ććŖé
åć®ćć”äøéØć ććčæć func createLeakySlice(size int ) [] int { fmt.Printf( " %dč¦ē“ ć®é
åćä½ęäø... \n " , size) large := make ([] int , size) for i := range large { large[i] = i } // ęåć®10č¦ē“ ć ććčæćļ¼ć”ć¢ćŖćŖć¼ćÆļ¼ļ¼ small := large[: 10 ] fmt.Printf( " čæćć¹ć©ć¤ć¹: len=%d, cap=%d \n " , len (small), cap (small)) return small } // ę¹åćććé¢ę°ļ¼åæ
č¦ćŖéØåć ććć³ćć¼ćć¦čæć func createFixedSlice(size int ) [] int { fmt.Printf( " %dč¦ē“ ć®é
åćä½ęäø... \n " , size) large := make ([] int , size) for i := range large { large[i] = i } // åæ
č¦ćŖéØåć ććć³ćć¼ small := make ([] int , 10 ) copy (small, large[: 10 ]) fmt.Printf( " čæćć¹ć©ć¤ć¹: len=%d, cap=%d \n " , len (small), cap (small)) return small // é¢ę°ēµäŗęć« large ćÆč§£ę¾ććć } func printMemoryStats(label string ) { runtime.GC() // å¼·å¶ēć«ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³ćå®č” runtime.GC() // 2åå®č”ćć¦ćć確å®ć« time.Sleep( 100 * time.Millisecond) // GCć®å®äŗćå¾
㤠var m runtime.MemStats runtime.ReadMemStats(&m) fmt.Printf( "%s: \n " , label) fmt.Printf( " Alloc: %.2f MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) \n " , float64 (m.Alloc)/ 1024 / 1024 ) fmt.Printf( " TotalAlloc: %.2f MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) \n " , float64 (m.TotalAlloc)/ 1024 / 1024 ) fmt.Printf( " Sys: %.2f MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) \n " , float64 (m.Sys)/ 1024 / 1024 ) fmt.Printf( " NumGC: %d (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) \n " , m.NumGC) fmt.Println() } func main() { fmt.Println( "=== ć”ć¢ćŖćŖć¼ćÆå®čؼå®éØ === \n " ) printMemoryStats( "åęē¶ę
" ) // å®éØ1: ć”ć¢ćŖćŖć¼ćÆććļ¼å¤§ććŖćµć¤ćŗć§ē¢ŗå®ć«ē¢ŗčŖļ¼ fmt.Println( "=== å®éØ1: ć”ć¢ćŖćŖć¼ćÆććļ¼åé”ć®ććććæć¼ć³ļ¼ ===" ) // č¤ę°ć®å¤§ććŖć¹ć©ć¤ć¹ćä½ęćć¦äæę sizes := [] int { 1000000 , 2000000 , 3000000 } // 1M, 2M, 3Mč¦ē“ for i, size := range sizes { fmt.Printf( "ć¹ććć %d: %dč¦ē“ ć®é
åćć10č¦ē“ ć¹ć©ć¤ć¹ćä½ę \n " , i+ 1 , size) leakySlice := createLeakySlice(size) // ć°ćć¼ćć«å¤ę°ć«äæåćć¦ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³ćé²ć globalSlices = append (globalSlices, leakySlice) printMemoryStats(fmt.Sprintf( "ć¹ććć %d å¾" , i+ 1 )) // åćé
åćåē
§ćć¦ććććØćē¢ŗčŖ fmt.Printf( " åē
§å
確čŖ: 容é=%d (å
ć®é
åćµć¤ćŗćØåć=%t) \n " , cap (leakySlice), cap (leakySlice) == size) fmt.Println( " ā 大ććŖé
åå
Øä½ćć”ć¢ćŖć«ę®ć£ć¦ććļ¼ \n " ) } fmt.Printf( "åé”ććæć¼ć³åčØ: %dåć®ć¹ć©ć¤ć¹ćäæę \n " , len (globalSlices)) fmt.Printf( "å®éć«ä½æēØćć¦ććč¦ē“ ę°: %d \n " , len (globalSlices)* 10 ) totalCapacity := 0 for _, s := range globalSlices { totalCapacity += cap (s) } fmt.Printf( "å®éć«ē¢ŗäæććć¦ćć容é: %d (%.0fåć®ē”é§) \n " , totalCapacity, float64 (totalCapacity)/ float64 ( len (globalSlices)* 10 )) printMemoryStats( "åé”ććæć¼ć³å®äŗå¾" ) // ć°ćć¼ćć«å¤ę°ććÆćŖć¢ globalSlices = nil printMemoryStats( "åé”ććæć¼ć³ćÆćŖć¢å¾" ) // å®éØ2: ć”ć¢ćŖćŖć¼ćÆćŖć fmt.Println( "=== å®éØ2: ć”ć¢ćŖćŖć¼ćÆćŖćļ¼ę¹åćććććæć¼ć³ļ¼ ===" ) var fixedSlices [][] int for i, size := range sizes { fmt.Printf( "ć¹ććć %d: %dč¦ē“ ć®é
åćć10č¦ē“ ć¹ć©ć¤ć¹ćä½ęļ¼ć³ćć¼ēļ¼ \n " , i+ 1 , size) fixedSlice := createFixedSlice(size) fixedSlices = append (fixedSlices, fixedSlice) printMemoryStats(fmt.Sprintf( "ę¹åć¹ććć %d å¾" , i+ 1 )) fmt.Printf( " åē
§å
確čŖ: 容é=%d (ęå°é=%t) \n " , cap (fixedSlice), cap (fixedSlice) == 10 ) fmt.Println( " ā åæ
č¦ćŖåć ćć”ć¢ćŖć使ēØļ¼ \n " ) } printMemoryStats( "ę¹åććæć¼ć³å®äŗå¾" ) // å®éØ3: å®éć®ć”ć¢ćŖć¢ćć¬ć¹ć®ęÆč¼ fmt.Println( "=== å®éØ3: ć”ć¢ćŖć¢ćć¬ć¹ęÆč¼å®éØ ===" ) demonstrateAddressComparison() } func demonstrateAddressComparison() { // 大ććŖé
åćä½ę bigArray := make ([] int , 1000000 ) for i := range bigArray { bigArray[i] = i } fmt.Printf( "å
ć®å¤§ććŖé
åć®ć¢ćć¬ć¹: 0x%x \n " , uintptr ( unsafe.Pointer (&bigArray[ 0 ]))) // åé”ć®ććć¹ć©ć¤ć·ć³ć° problematicSlice := bigArray[: 5 ] fmt.Printf( "åé”ć¹ć©ć¤ć¹ć®ć¢ćć¬ć¹: 0x%x (åć=%t) \n " , uintptr ( unsafe.Pointer (&problematicSlice[ 0 ])), unsafe.Pointer (&bigArray[ 0 ]) == unsafe.Pointer (&problematicSlice[ 0 ])) // ę¹åćććć³ćć¼ fixedSlice := make ([] int , 5 ) copy (fixedSlice, bigArray[: 5 ]) fmt.Printf( "ę¹åć¹ć©ć¤ć¹ć®ć¢ćć¬ć¹: 0x%x (ē°ćŖć=%t) \n " , uintptr ( unsafe.Pointer (&fixedSlice[ 0 ])), unsafe.Pointer (&bigArray[ 0 ]) != unsafe.Pointer (&fixedSlice[ 0 ])) fmt.Println( " \n ć”ć¢ćŖåē
§ć®éć:" ) fmt.Printf( "åé”ć¹ć©ć¤ć¹: len=%d, cap=%d (大ććŖé
åćåē
§) \n " , len (problematicSlice), cap (problematicSlice)) fmt.Printf( "ę¹åć¹ć©ć¤ć¹: len=%d, cap=%d (ē¬ē«ććå°ććŖé
å) \n " , len (fixedSlice), cap (fixedSlice)) // bigArrayćnilć«ćć¦ććproblematicSlicećåē
§ćäæę fmt.Println( " \n å
ć®é
åćnilć«ććå “å:" ) bigArray = nil runtime.GC() fmt.Printf( "problematicSlice[0] = %d (ć¾ć ć¢ćÆć»ć¹åÆč½) \n " , problematicSlice[ 0 ]) fmt.Printf( "容éćÆä¾ē¶ćØćć¦: %d \n " , cap (problematicSlice)) fmt.Println( "ā 大ććŖé
åćÆč§£ę¾ććć¦ććŖćļ¼" ) } å®č”ēµę === ć”ć¢ćŖćŖć¼ćÆå®čؼå®éØ === åęē¶ę
: Alloc: 0.11 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 0.12 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 6.52 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 2 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) === å®éØ1: ć”ć¢ćŖćŖć¼ćÆććļ¼åé”ć®ććććæć¼ć³ļ¼ === ć¹ććć 1: 1000000č¦ē“ ć®é
åćć10č¦ē“ ć¹ć©ć¤ć¹ćä½ę 1000000č¦ē“ ć®é
åćä½ęäø... čæćć¹ć©ć¤ć¹: len=10, cap=1000000 ć¹ććć 1 å¾: Alloc: 7.75 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 7.75 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 14.52 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 5 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) åē
§å
確čŖ: 容é=1000000 (å
ć®é
åćµć¤ćŗćØåć=true) ā 大ććŖé
åå
Øä½ćć”ć¢ćŖć«ę®ć£ć¦ććļ¼ ć¹ććć 2: 2000000č¦ē“ ć®é
åćć10č¦ē“ ć¹ć©ć¤ć¹ćä½ę 2000000č¦ē“ ć®é
åćä½ęäø... čæćć¹ć©ć¤ć¹: len=10, cap=2000000 ć¹ććć 2 å¾: Alloc: 23.02 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 23.02 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 30.52 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 8 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) åē
§å
確čŖ: 容é=2000000 (å
ć®é
åćµć¤ćŗćØåć=true) ā 大ććŖé
åå
Øä½ćć”ć¢ćŖć«ę®ć£ć¦ććļ¼ ć¹ććć 3: 3000000č¦ē“ ć®é
åćć10č¦ē“ ć¹ć©ć¤ć¹ćä½ę 3000000č¦ē“ ć®é
åćä½ęäø... čæćć¹ć©ć¤ć¹: len=10, cap=3000000 ć¹ććć 3 å¾: Alloc: 45.91 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 45.92 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 54.52 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 11 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) åē
§å
確čŖ: 容é=3000000 (å
ć®é
åćµć¤ćŗćØåć=true) ā 大ććŖé
åå
Øä½ćć”ć¢ćŖć«ę®ć£ć¦ććļ¼ åé”ććæć¼ć³åčØ: 3åć®ć¹ć©ć¤ć¹ćäæę å®éć«ä½æēØćć¦ććč¦ē“ ę°: 30 å®éć«ē¢ŗäæććć¦ćć容é: 6000000 (200000åć®ē”é§) åé”ććæć¼ć³å®äŗå¾: Alloc: 45.91 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 45.92 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 54.52 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 13 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) åé”ććæć¼ć³ćÆćŖć¢å¾: Alloc: 0.12 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 45.92 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 54.52 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 15 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) === å®éØ2: ć”ć¢ćŖćŖć¼ćÆćŖćļ¼ę¹åćććććæć¼ć³ļ¼ === ć¹ććć 1: 1000000č¦ē“ ć®é
åćć10č¦ē“ ć¹ć©ć¤ć¹ćä½ęļ¼ć³ćć¼ēļ¼ 1000000č¦ē“ ć®é
åćä½ęäø... čæćć¹ć©ć¤ć¹: len=10, cap=10 ę¹åć¹ććć 1 å¾: Alloc: 0.12 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 53.56 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 54.77 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 18 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) åē
§å
確čŖ: 容é=10 (ęå°é=true) ā åæ
č¦ćŖåć ćć”ć¢ćŖć使ēØļ¼ ć¹ććć 2: 2000000č¦ē“ ć®é
åćć10č¦ē“ ć¹ć©ć¤ć¹ćä½ęļ¼ć³ćć¼ēļ¼ 2000000č¦ē“ ć®é
åćä½ęäø... čæćć¹ć©ć¤ć¹: len=10, cap=10 ę¹åć¹ććć 2 å¾: Alloc: 0.12 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 68.83 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 54.77 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 21 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) åē
§å
確čŖ: 容é=10 (ęå°é=true) ā åæ
č¦ćŖåć ćć”ć¢ćŖć使ēØļ¼ ć¹ććć 3: 3000000č¦ē“ ć®é
åćć10č¦ē“ ć¹ć©ć¤ć¹ćä½ęļ¼ć³ćć¼ēļ¼ 3000000č¦ē“ ć®é
åćä½ęäø... čæćć¹ć©ć¤ć¹: len=10, cap=10 ę¹åć¹ććć 3 å¾: Alloc: 0.12 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 91.72 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 54.77 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 24 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) åē
§å
確čŖ: 容é=10 (ęå°é=true) ā åæ
č¦ćŖåć ćć”ć¢ćŖć使ēØļ¼ ę¹åććæć¼ć³å®äŗå¾: Alloc: 0.12 MB (ē¾åØä½æēØäøć®ć”ć¢ćŖ) TotalAlloc: 91.72 MB (瓯čØå²ćå½ć¦ć”ć¢ćŖ) Sys: 54.77 MB (ć·ć¹ćć ććåå¾ććć”ć¢ćŖ) NumGC: 26 (ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³åę°) === å®éØ3: ć”ć¢ćŖć¢ćć¬ć¹ęÆč¼å®éØ === å
ć®å¤§ććŖé
åć®ć¢ćć¬ć¹: 0x400018c000 åé”ć¹ć©ć¤ć¹ć®ć¢ćć¬ć¹: 0x400018c000 (åć=true) ę¹åć¹ć©ć¤ć¹ć®ć¢ćć¬ć¹: 0x40000d7c08 (ē°ćŖć=true) ć”ć¢ćŖåē
§ć®éć: åé”ć¹ć©ć¤ć¹: len=5, cap=1000000 (大ććŖé
åćåē
§) ę¹åć¹ć©ć¤ć¹: len=5, cap=5 (ē¬ē«ććå°ććŖé
å) å
ć®é
åćnilć«ććå “å: problematicSlice[0] = 0 (ć¾ć ć¢ćÆć»ć¹åÆč½) 容éćÆä¾ē¶ćØćć¦: 1000000 ā 大ććŖé
åćÆč§£ę¾ććć¦ććŖćļ¼ ćÆć¤ćŗ3 ## **šÆ ćÆć¤ćŗē¬¬3å** ä»åŗ¦ćÆćć¹ć©ć¤ć¹ć®**ć”ć¢ćŖćŖć¼ćÆćØå
±ęé
åć®åé”**ć«ć¤ćć¦å¦ēæćć¾ćććć ćµć³ćć«5ć®å®č”ēµęćØåé”ē¹ćäŗę³ćć¦ćć ććļ¼ **č³Ŗåļ¼** 1. ` small ` ć®é·ććØå®¹éćÆććć¤ć«ćŖćć§ććććļ¼ 2. 100äøč¦ē“ ć®å¤§ććŖé
åćÆć¬ćć¼ćøć³ć¬ćÆć·ć§ć³ćććć§ććććļ¼ 3. ććć¬ćć¼ćøć³ć¬ćÆć·ć§ć³ćććŖćå “åććŖćć§ććććļ¼ ćććÆå®éć®éēŗć§ććééćć**ć”ć¢ćŖćŖć¼ćÆ**ć®åå ćØćŖćéč¦ćŖåé”ć§ććććŖćć®äŗę³ććčćććć ććļ¼ ććć§ćÆćć¹ć©ć¤ć¹čµ·å ć®ć”ć¢ćŖćŖć¼ćÆć«ć¤ćć¦ę¤čؼćć¾ććć ļ¼ē¢ŗäæć”ć¢ćŖé åć®č§£ę¾åæćć§ćÆćŖć slice ć®åē
§ć«ććę®åćŖć®ć§ć å³åÆć«ćÆć”ć¢ćŖćŖć¼ćÆćØćÆčØććŖćććććć¾ććććććć§ćÆć”ć¢ćŖćŖć¼ćÆćØććęčć§č©±ćé²ćć¦ććć¾ććļ¼ ćć®ć¹ćććć®ę¤čؼććć仄äøć®ćććŖčåÆćå¾ćććØćć§ćć¾ććć ć¹ć©ć¤ć¹ćÆé
åćøć®åē
§ć§ćććéØåć¹ć©ć¤ć¹ćēåćć¦ććéććå
é
å㯠GC ć§č§£ę¾ćććŖćć ć¹ć©ć¤ć¹ćå°ććć¦ć大ććé
åćåē
§ćć¦ććå “åćÆćé
åć確äæćć¦ćć大ććŖć”ć¢ćŖé åćÆč§£ę¾ćććŖćć åē
§ćę®ććŖććć°čÆćć®ć§ć copy é¢ę°ćŖć©ćå©ēØććććØć§åéæåÆč½ ęååć«ćććć”ć¢ćŖćŖć¼ćÆ ćµć³ćć«6ļ¼å®č£
ļ¼å®č”ēµęļ¼ å®č£
package main import ( "bufio" "fmt" "os" "runtime" "strings" "sync" "time" "unsafe" ) // 大ććŖćć¹ććć”ć¤ć«ćä½ęļ¼ē“50MBļ¼ func createLargeTestLogFile() { file, err := os.Create( "large_test.log" ) if err != nil { fmt.Printf( "ćć”ć¤ć«ä½ęćØć©ć¼: %v \n " , err) return } defer file.Close() // ē“50MBć®ćć°ćć”ć¤ć«ćēę for i := 0 ; i < 500000 ; i++ { if i% 10000 == 0 { file.WriteString(fmt.Sprintf( "ERROR: Critical error occurred at line %d - %s \n " , i, strings.Repeat( "important data " , 10 ))) } else { file.WriteString(fmt.Sprintf( "INFO: Normal operation at line %d - %s \n " , i, strings.Repeat( "lorem ipsum dolor sit amet consectetur adipiscing elit " , 5 ))) } } fmt.Printf( "大ććŖćć¹ććć”ć¤ć« (large_test.log) ćä½ęćć¾ćć \n " ) } // åé”ć®ććå
ć®ć³ć¼ćļ¼ććę確ć«åé”ć示ććć¼ćøć§ć³ļ¼ func processLogFileProblematic(filename string ) [] string { content, err := os.ReadFile(filename) if err != nil { return nil } // éč¦: ęååå¤ęć§å
ć®ćć¤ćé
åćØćÆå„ć«ęååēØć”ć¢ćŖćē¢ŗäæ contentStr := string (content) lines := strings.Split(contentStr, " \n " ) var errorLines [] string for _, line := range lines { if strings.Contains(line, "ERROR" ) { // ćććåé”: line 㯠contentStr ćøć®åē
§ errorLines = append (errorLines, line) } } // content 㨠contentStr ćÆćÆćŖć¢ćć¦ćć // errorLines ć®åč¦ē“ ć contentStr ćøć®åē
§ćäæę return errorLines } // ę¹åē1: ć¹ććŖć¼ćć³ć°å¦ē func processLogFileStreaming(filename string ) [] string { file, err := os.Open(filename) if err != nil { return nil } defer file.Close() var errorLines [] string scanner := bufio.NewScanner(file) for scanner.Scan() { line := scanner.Text() if strings.Contains(line, "ERROR" ) { // strings.Clone ć§å
ćć”ć¤ć«ćøć®åē
§ćåę errorLines = append (errorLines, strings.Clone(line)) } } return errorLines } // ę¹åē4-1: ćć”ć¤ć«åå²å¦ē func processLogFileChunked(filename string , chunkSize int64 ) [] string { file, err := os.Open(filename) if err != nil { return nil } defer file.Close() var errorLines [] string // ćć”ć¤ć«ćęå®ćµć¤ćŗć®ćć£ć³ćÆć«åå²ćć¦å¦ē buffer := make ([] byte , chunkSize) var remainder [] byte for { n, err := file.Read(buffer) if n == 0 { break } // ååć®ä½ććØä»åčŖćć ćć¼ćæćēµå chunk := append (remainder, buffer[:n]...) // ęå¾ć®äøå®å
ØćŖč”ćꬔåć«ęć”č¶ć lastNewline := strings.LastIndex( string (chunk), " \n " ) if lastNewline == - 1 { remainder = chunk continue } processChunk := chunk[:lastNewline] remainder = chunk[lastNewline+ 1 :] // ćć£ć³ćÆå
ć§ćØć©ć¼č”ćę¤ē“¢ lines := strings.Split( string (processChunk), " \n " ) for _, line := range lines { if strings.Contains(line, "ERROR" ) { errorLines = append (errorLines, strings.Clone(line)) } } if err != nil { break } } // ęå¾ć®ä½ććå¦ē if len (remainder) > 0 && strings.Contains( string (remainder), "ERROR" ) { errorLines = append (errorLines, strings.Clone( string (remainder))) } return errorLines } // ę¹åē4-2: äø¦åå¦ē func processLogFileParallel(filename string ) [] string { content, err := os.ReadFile(filename) if err != nil { return nil } lines := strings.Split( string (content), " \n " ) // ćÆć¼ć«ć¼ę° numWorkers := runtime.NumCPU() chunkSize := len (lines) / numWorkers var wg sync.WaitGroup var mu sync.Mutex var errorLines [] string for i := 0 ; i < numWorkers; i++ { wg.Add( 1 ) go func (start, end int ) { defer wg.Done() var localErrors [] string for j := start; j < end && j < len (lines); j++ { if strings.Contains(lines[j], "ERROR" ) { localErrors = append (localErrors, strings.Clone(lines[j])) } } mu.Lock() errorLines = append (errorLines, localErrors...) mu.Unlock() }(i*chunkSize, (i+ 1 )*chunkSize) } wg.Wait() return errorLines } // ę¹åē4-3: ć¤ć³ćććÆć¹å©ēØ type LogIndex struct { ErrorLineNumbers [] int filename string } func buildLogIndex(filename string ) *LogIndex { file, err := os.Open(filename) if err != nil { return nil } defer file.Close() var errorLines [] int scanner := bufio.NewScanner(file) lineNumber := 0 for scanner.Scan() { if strings.Contains(scanner.Text(), "ERROR" ) { errorLines = append (errorLines, lineNumber) } lineNumber++ } return &LogIndex{ ErrorLineNumbers: errorLines, filename: filename, } } func (idx *LogIndex) GetErrorLines() [] string { file, err := os.Open(idx.filename) if err != nil { return nil } defer file.Close() var errorLines [] string scanner := bufio.NewScanner(file) lineNumber := 0 errorIndex := 0 for scanner.Scan() && errorIndex < len (idx.ErrorLineNumbers) { if lineNumber == idx.ErrorLineNumbers[errorIndex] { errorLines = append (errorLines, strings.Clone(scanner.Text())) errorIndex++ } lineNumber++ } return errorLines } func printMemoryStats(label string ) { runtime.GC() runtime.GC() time.Sleep( 100 * time.Millisecond) var m runtime.MemStats runtime.ReadMemStats(&m) fmt.Printf( "%s: %.2f MB \n " , label, float64 (m.Alloc)/ 1024 / 1024 ) } func demonstrateMemoryLeak() { fmt.Println( "=== å®éć®ć”ć¢ćŖćŖć¼ćÆå®čؼļ¼å¤§ććŖćć”ć¤ć«ä½æēØļ¼ ===" ) printMemoryStats( "åęē¶ę
" ) // åé”ć®ćććć¼ćøć§ć³ć§ć”ć¢ćŖćŖć¼ćÆćå®čؼ fmt.Println( "åé”ć®ćććć¼ćøć§ć³å®č”..." ) // ć”ć¢ćŖćŖć¼ćÆćē¶ęććććć«ēµęćäæę var leakyResults [] string leakyResults = processLogFileProblematic( "large_test.log" ) fmt.Printf( "ćØć©ć¼č”ę°: %d \n " , len (leakyResults)) printMemoryStats( "åé”ēå®č”å¾ļ¼ēµęäæęäøļ¼" ) // ēµęć®ęååćå
ćć”ć¤ć«ćøć®åē
§ćäæęćć¦ććććØć証ę fmt.Printf( "ęåć®ćØć©ć¼č”ć®ć¢ćć¬ć¹: 0x%x \n " , (*(* unsafe.Pointer )( unsafe.Pointer (&leakyResults[ 0 ])))) // leakyResultsććÆćŖć¢ććć¾ć§ć”ć¢ćŖćÆč§£ę¾ćććŖć fmt.Println( "ēµęććÆćŖć¢ćć¾ć..." ) leakyResults = nil printMemoryStats( "åé”ēēµęćÆćŖć¢å¾" ) // ę¹åēć®å®č” fmt.Println( "ę¹åēļ¼ć¹ććŖć¼ćć³ć°ļ¼å®č”..." ) streamingResults := processLogFileStreaming( "large_test.log" ) fmt.Printf( "ćØć©ć¼č”ę°: %d \n " , len (streamingResults)) printMemoryStats( "ę¹åēå®č”å¾" ) fmt.Printf( "ę¹åēćØć©ć¼č”ć®ć¢ćć¬ć¹: 0x%x \n " , (*(* unsafe.Pointer )( unsafe.Pointer (&streamingResults[ 0 ])))) fmt.Println( "ā ē°ćŖćć¢ćć¬ć¹ = ē¬ē«ććęåå" ) } func compareAllApproaches() { fmt.Println( " \n === å
Øę¹åēć®ććć©ć¼ćć³ć¹ęÆč¼ ===" ) approaches := [] struct { name string fn func ( string ) [] string }{ { "åé”ē" , processLogFileProblematic}, { "ć¹ććŖć¼ćć³ć°ē" , processLogFileStreaming}, { "ćć£ć³ćÆåå²ē" , func (f string ) [] string { return processLogFileChunked(f, 1024 * 1024 ) }}, // 1MB chunks { "äø¦åå¦ēē" , processLogFileParallel}, } for _, approach := range approaches { start := time.Now() result := approach.fn( "large_test.log" ) duration := time.Since(start) fmt.Printf( "%-12s: %v (%dč”) \n " , approach.name, duration, len (result)) } // ć¤ć³ćććÆć¹å©ēØć®ćć¹ć fmt.Println( " \n ć¤ć³ćććÆć¹å©ēØē:" ) start := time.Now() index := buildLogIndex( "large_test.log" ) indexBuildTime := time.Since(start) start = time.Now() indexResults := index.GetErrorLines() queryTime := time.Since(start) fmt.Printf( " ć¤ć³ćććÆć¹ę§ēÆ: %v \n " , indexBuildTime) fmt.Printf( " ćÆćØćŖå®č”: %v (%dč”) \n " , queryTime, len (indexResults)) fmt.Printf( " åčØęé: %v \n " , indexBuildTime+queryTime) } func main() { fmt.Println( "=== ę¹åēåęćØć”ć¢ćŖćŖć¼ćÆå®čؼ === \n " ) // 大ććŖćć¹ććć”ć¤ć«ćä½ę createLargeTestLogFile() // å®éć®ć”ć¢ćŖćŖć¼ćÆćå®čؼ demonstrateMemoryLeak() // å
Øę¹åēć®ęÆč¼ compareAllApproaches() // ę¹åēć®č©³ē“°č§£čŖ¬ explainAdvancedStrategies() } func explainAdvancedStrategies() { fmt.Println( " \n === ę¹åē4ć®č©³ē“°č§£čŖ¬ ===" ) fmt.Println( "1. ćć”ć¤ć«åå²å¦ē:" ) fmt.Println( " ā
ćć”ć¤ć«ćå°ććŖćć£ć³ćÆļ¼ä¾ļ¼1MBļ¼ć«åå²" ) fmt.Println( " ā
ć”ć¢ćŖä½æēØéćäøå®ć«äæę" ) fmt.Println( " ā
巨大ćć”ć¤ć«ć§ćå¦ēåÆč½" ) fmt.Println( " ā ļø č”ć®å¢ēćé©åć«å¦ēććåæ
č¦" ) fmt.Println( " \n 2. äø¦åå¦ē:" ) fmt.Println( " ā
CPUć³ć¢ę°ć«åæćć¦ćÆć¼ć«ć¼ćčµ·å" ) fmt.Println( " ā
ćć”ć¤ć«ćåå²ćć¦äø¦åę¤ē“¢" ) fmt.Println( " ā
ćć«ćć³ć¢CPUć§é«éå" ) fmt.Println( " ā ļø ć”ć¢ćŖä½æēØéćÆå¢å " ) fmt.Println( " \n 3. ć¤ć³ćććÆć¹å©ēØ:" ) fmt.Println( " ā
äŗåć«ćØć©ć¼č”ć®ä½ē½®ćć¤ć³ćććÆć¹å" ) fmt.Println( " ā
åććć”ć¤ć«ćä½åŗ¦ćę¤ē“¢ććå “åć«å¹ēē" ) fmt.Println( " ā
éØåēćŖēµęåå¾ćé«é" ) fmt.Println( " ā ļø ć¤ć³ćććÆć¹ę§ēÆęéćåæ
č¦" ) fmt.Println( " \n 4. ćć®ä»ć®é«åŗ¦ćŖęę³:" ) fmt.Println( " - Memory-mapped files (mmap)" ) fmt.Println( " - å§ēø®ćć”ć¤ć«ć®ē“ę„å¦ē" ) fmt.Println( " - ćć¼ćæćć¼ć¹ćøć®äŗåć¤ć³ćć¼ć" ) fmt.Println( " - ę£č¦č”Øē¾ć®ęé©å" ) } å®č”ēµę === ę¹åēåęćØć”ć¢ćŖćŖć¼ćÆå®čؼ === 大ććŖćć¹ććć”ć¤ć« (large _ test.log) ćä½ęćć¾ćć === å®éć®ć”ć¢ćŖćŖć¼ćÆå®čؼļ¼å¤§ććŖćć”ć¤ć«ä½æēØļ¼ === åęē¶ę
: 0.12 MB åé”ć®ćććć¼ćøć§ć³å®č”... ćØć©ć¼č”ę°: 50 åé”ēå®č”å¾ļ¼ēµęäæęäøļ¼: 150.69 MB ęåć®ćØć©ć¼č”ć®ć¢ćć¬ć¹: 0x4009c12000 ēµęććÆćŖć¢ćć¾ć... åé”ēēµęćÆćŖć¢å¾: 0.12 MB ę¹åēļ¼ć¹ććŖć¼ćć³ć°ļ¼å®č”... ćØć©ć¼č”ę°: 50 ę¹åēå®č”å¾: 0.13 MB ę¹åēćØć©ć¼č”ć®ć¢ćć¬ć¹: 0x400009e0d0 ā ē°ćŖćć¢ćć¬ć¹ = ē¬ē«ććęåå === å
Øę¹åēć®ććć©ć¼ćć³ć¹ęÆč¼ === åé”ē : 325.162209ms (50č”) ć¹ććŖć¼ćć³ć°ē : 94.33525ms (50č”) ćć£ć³ćÆåå²ē : 253.834459ms (50č”) äø¦åå¦ēē : 852.810793ms (50č”) ć¤ć³ćććÆć¹å©ēØē: ć¤ć³ćććÆć¹ę§ēÆ: 1.729318959s ćÆćØćŖå®č”: 107.052958ms (50č”) åčØęé: 1.836371917s === ę¹åē4ć®č©³ē“°č§£čŖ¬ === 1. ćć”ć¤ć«åå²å¦ē: ā
ćć”ć¤ć«ćå°ććŖćć£ć³ćÆļ¼ä¾ļ¼1MBļ¼ć«åå² ā
ć”ć¢ćŖä½æēØéćäøå®ć«äæę ā
巨大ćć”ć¤ć«ć§ćå¦ēåÆč½ ā ļø č”ć®å¢ēćé©åć«å¦ēććåæ
č¦ 2. äø¦åå¦ē: ā
CPUć³ć¢ę°ć«åæćć¦ćÆć¼ć«ć¼ćčµ·å ā
ćć”ć¤ć«ćåå²ćć¦äø¦åę¤ē“¢ ā
ćć«ćć³ć¢CPUć§é«éå ā ļø ć”ć¢ćŖä½æēØéćÆå¢å 3. ć¤ć³ćććÆć¹å©ēØ: ā
äŗåć«ćØć©ć¼č”ć®ä½ē½®ćć¤ć³ćććÆć¹å ā
åććć”ć¤ć«ćä½åŗ¦ćę¤ē“¢ććå “åć«å¹ēē ā
éØåēćŖēµęåå¾ćé«é ā ļø ć¤ć³ćććÆć¹ę§ēÆęéćåæ
č¦ 4. ćć®ä»ć®é«åŗ¦ćŖęę³: - Memory-mapped files (mmap) - å§ēø®ćć”ć¤ć«ć®ē“ę„å¦ē - ćć¼ćæćć¼ć¹ćøć®äŗåć¤ć³ćć¼ć - ę£č¦č”Øē¾ć®ęé©å ćÆć¤ćŗ4 ## **šÆ ęēµå¦ēæē¢ŗčŖćÆć¤ćŗ** ē“ ę“ćććēč§£åć示ćć¦ććć ććć®ć§ćęēµåé”ć«é²ćæć¾ćććļ¼ **åé”**: åé”ć®ććć³ć¼ćä¾ć®åé”ē¹ćØę¹åēćčŖ¬ęćć¦ćć ććļ¼ **åęé
ē®:** 1. **ć”ć¢ćŖå¹ēę§**ć®åé”ē¹ 2. **ęéčØē®é**ć®åé”ē¹ 3. **å
·ä½ēćŖę¹åē**ć2ć¤ä»„äø ććŖćć®ć¹ć©ć¤ć¹å¦ēæć®é大ęćØćć¦ćåęććčćććć ććļ¼ ć¹ć©ć¤ć¹ć®ć”ć¢ćŖćŖć¼ćÆć®č©±ććēŗå±ćć¦ćęååć®ć”ć¢ćŖćŖć¼ćÆć«ć¤ćć¦ć®ę¤čؼćå®ę½ćć¾ććć ććć§ćÆćåé”ć®ććć³ć¼ćļ¼ä»„äøåē
§ļ¼ćę示ććććć®åé”ē¹ćØę¹åēćčćććććć¾ććć func processLogFile(filename string ) [] string { // 10MB ć®ćć°ćć”ć¤ć«ćčŖćæč¾¼ćæ content, _ := os.ReadFile(filename) // 10MB lines := strings.Split( string (content), " \n " ) // 100äøč” // ćØć©ć¼č”ć ććę½åŗļ¼éåøøćÆę°č”ļ¼ var errorLines [] string for _, line := range lines { if strings.Contains(line, "ERROR" ) { errorLines = append (errorLines, line) } } return errorLines // éåøøćÆ2-3č” } Go ć® string åćÆćå
éØēć«ćÆćå®ćć¼ćæćć¤ćåćøć®ćć¤ć³ćæććØćé·ćććęć¤ę§é ä½ć§ć 5 ć type stringStruct struct { str unsafe.Pointer len int } å®éć«ć仄äøć®ćććŖć³ć¼ćć§ string åć®å¤ę°ć for ęć§ć«ć¼ćććććØćåÆč½ć§ćć func forString() { a := "hello, world" for i, s := range a { fmt.Println(i, s) } } äøčØćčøć¾ćććØććć®ć³ć¼ćć«ć¤ćć¦ä»„äøć®ćććŖåé”ē¹ćØę¹åēćčćććć¾ćć åé”ē¹: os.ReadFile ć§å¤§ććŖćć”ć¤ć«ć®å
Øä½ćäøåŗ¦ć«čŖćæč¾¼ćć§ćć strings.Split ć®åč”ćå
ć®ęååćåē
§ććć®ć§ćé¢ę°ēµäŗå¾ćć”ć¢ćŖć«ę®åććGCć§č§£ę¾ćććŖć ć«ć¼ćć§å¤§ććŖć¹ć©ć¤ć¹ć®č¦ē“ å
Øć¦ćčµ°ę»ćć¦ćć ę¹åē: é·ććę¢ē„ć®å “åćÆäŗåć«å®¹éć確äæććććØć§åå²ćå½ć¦ćåęø äø¦åå¦ē ę§é ä½ćå°å
„ćć¦åÆ¾č±”ćØćŖćć¤ć³ćććÆć¹ćäæęććććØć§ć¤ć³ćććÆć¹åē
§ćć éØåēćŖēµęåå¾ćē¹°ćčæćę¤ē“¢ć«ęå¹ ćć£ć³ćÆå¦ē ć¹ććŖć¼ćć³ć°å¦ē å¤ę¬”å
ć¹ć©ć¤ć¹ć®ć«ć¼ćå¦ē ćµć³ćć«7ļ¼å®č£
ļ¼å®č”ēµęļ¼ å®č£
package main import ( "fmt" "math/rand" "runtime" "time" "unsafe" ) // čØē®éć®åęćØććć©ć¼ćć³ć¹ęø¬å®ćč”ćé¢ę° func measurePerformance(name string , fn func ()) time.Duration { runtime.GC() // ęø¬å®åć«GCćå®č” start := time.Now() fn() duration := time.Since(start) fmt.Printf( "%-25s: %v \n " , name, duration) return duration } // 1. O(n^2) - åŗę¬ēćŖ2éć«ć¼ć func basicNestedLoop(size int ) { data := make ([][] int , size) for i := range data { data[i] = make ([] int , size) } // éå¹ēćŖć¢ćÆć»ć¹ććæć¼ć³ļ¼ååŖå
ļ¼ for j := 0 ; j < size; j++ { for i := 0 ; i < size; i++ { data[i][j] = i + j } } } // 2. ę¹åē - ćć£ćć·ć„å¹ēć®čÆćć¢ćÆć»ć¹ććæć¼ć³ func optimizedNestedLoop(size int ) { data := make ([][] int , size) for i := range data { data[i] = make ([] int , size) } // å¹ēēćŖć¢ćÆć»ć¹ććæć¼ć³ļ¼č”åŖå
ļ¼ for i := 0 ; i < size; i++ { for j := 0 ; j < size; j++ { data[i][j] = i + j } } } // 3. 1ꬔå
ć¹ć©ć¤ć¹ć使ēØććęé©å func flattenedArrayOptimization(size int ) { // 2ꬔå
é
åć1ꬔå
é
åćØćć¦č”Øē¾ data := make ([] int , size*size) for i := 0 ; i < size; i++ { for j := 0 ; j < size; j++ { // 2ꬔå
åŗ§ęØć1ꬔå
ć¤ć³ćććÆć¹ć«å¤ę data[i*size+j] = i + j } } } // 4. O(n^3) - č”åä¹ē®ć®ä¾ func matrixMultiplication(a, b [][] int , size int ) [][] int { result := make ([][] int , size) for i := range result { result[i] = make ([] int , size) } // ęØęŗēćŖč”åä¹ē® O(n^3) for i := 0 ; i < size; i++ { for j := 0 ; j < size; j++ { for k := 0 ; k < size; k++ { result[i][j] += a[i][k] * b[k][j] } } } return result } // 5. ęé©åćććč”åä¹ē®ļ¼ć«ć¼ćé åŗć®ę¹åļ¼ func optimizedMatrixMultiplication(a, b [][] int , size int ) [][] int { result := make ([][] int , size) for i := range result { result[i] = make ([] int , size) } // ć«ć¼ćé åŗćå¤ę“ćć¦ćć£ćć·ć„å¹ēćę¹å for i := 0 ; i < size; i++ { for k := 0 ; k < size; k++ { for j := 0 ; j < size; j++ { result[i][j] += a[i][k] * b[k][j] } } } return result } // 6. ććććÆåć«ććęé©å func blockedMatrixMultiplication(a, b [][] int , size, blockSize int ) [][] int { result := make ([][] int , size) for i := range result { result[i] = make ([] int , size) } // ććććÆåä½ć§å¦ēćć¦ćć£ćć·ć„å¹ēćę大å for ii := 0 ; ii < size; ii += blockSize { for jj := 0 ; jj < size; jj += blockSize { for kk := 0 ; kk < size; kk += blockSize { // ććććÆå
ć®å¦ē maxI := min(ii+blockSize, size) maxJ := min(jj+blockSize, size) maxK := min(kk+blockSize, size) for i := ii; i < maxI; i++ { for j := jj; j < maxJ; j++ { for k := kk; k < maxK; k++ { result[i][j] += a[i][k] * b[k][j] } } } } } } return result } // 7. äø¦ååć«ććęé©å func parallelMatrixMultiplication(a, b [][] int , size int ) [][] int { result := make ([][] int , size) for i := range result { result[i] = make ([] int , size) } numWorkers := runtime.NumCPU() rowsPerWorker := size / numWorkers done := make ( chan bool , numWorkers) for worker := 0 ; worker < numWorkers; worker++ { startRow := worker * rowsPerWorker endRow := startRow + rowsPerWorker if worker == numWorkers- 1 { endRow = size // ęå¾ć®ćÆć¼ć«ć¼ćÆę®ććå
Øć¦å¦ē } go func (start, end int ) { for i := start; i < end; i++ { for j := 0 ; j < size; j++ { for k := 0 ; k < size; k++ { result[i][j] += a[i][k] * b[k][j] } } } done <- true }(startRow, endRow) } // å
ØćÆć¼ć«ć¼ć®å®äŗćå¾
ę© for i := 0 ; i < numWorkers; i++ { <-done } return result } // 8. ć”ć¢ćŖć¢ćÆć»ć¹ććæć¼ć³ć®åę func analyzeMemoryAccessPatterns() { fmt.Println( "=== ć”ć¢ćŖć¢ćÆć»ć¹ććæć¼ć³ć®åę ===" ) size := 1000 // č”åŖå
ć¢ćÆć»ć¹ data := make ([][] int , size) for i := range data { data[i] = make ([] int , size) } fmt.Printf( "2ꬔå
ć¹ć©ć¤ć¹ć®ć”ć¢ćŖć¬ć¤ć¢ć¦ćåę: \n " ) fmt.Printf( "dataé
åć®ć¢ćć¬ć¹: 0x%x \n " , uintptr ( unsafe.Pointer (&data[ 0 ]))) for i := 0 ; i < 3 ; i++ { fmt.Printf( "data[%d]ć®ć¢ćć¬ć¹: 0x%x \n " , i, uintptr ( unsafe.Pointer (&data[i][ 0 ]))) if i > 0 { prevAddr := uintptr ( unsafe.Pointer (&data[i- 1 ][ 0 ])) currAddr := uintptr ( unsafe.Pointer (&data[i][ 0 ])) fmt.Printf( " åć®č”ćØć®å·®: %d ćć¤ć \n " , currAddr-prevAddr) } } // 1ꬔå
é
åć§ć®é£ē¶ć¢ćÆć»ć¹ flatData := make ([] int , size*size) fmt.Printf( " \n 1ꬔå
ć¹ć©ć¤ć¹ć®ć”ć¢ćŖć¬ć¤ć¢ć¦ć: \n " ) fmt.Printf( "flatData[0]ć®ć¢ćć¬ć¹: 0x%x \n " , uintptr ( unsafe.Pointer (&flatData[ 0 ]))) fmt.Printf( "flatData[1000]ć®ć¢ćć¬ć¹: 0x%x \n " , uintptr ( unsafe.Pointer (&flatData[ 1000 ]))) fmt.Printf( "é£ē¶ććč¦ē“ ć®å·®: %d ćć¤ć \n " , uintptr ( unsafe.Pointer (&flatData[ 1 ]))- uintptr ( unsafe.Pointer (&flatData[ 0 ]))) } // čØē®éć®å®čؼå®éØ func demonstrateComplexityGrowth() { fmt.Println( " \n === čØē®éć®å®čؼå®éØ ===" ) sizes := [] int { 100 , 200 , 400 , 800 } fmt.Println( "åŗę¬ēćŖ2éć«ć¼ć O(n^2):" ) var prevDuration time.Duration for i, size := range sizes { duration := measurePerformance(fmt.Sprintf( "ćµć¤ćŗ %d" , size), func () { basicNestedLoop(size) }) if i > 0 { ratio := float64 (duration) / float64 (prevDuration) theoretical := float64 (size*size) / float64 (sizes[i- 1 ]*sizes[i- 1 ]) fmt.Printf( " å®ęø¬ęÆē: %.2fx, ēč«å¤(n^2): %.2fx \n " , ratio, theoretical) } prevDuration = duration } fmt.Println( " \n č”åä¹ē® O(n^3):" ) prevDuration = 0 for i, size := range sizes[: 3 ] { // ćµć¤ćŗćå¶éļ¼ęéććććććļ¼ a := createRandomMatrix(size) b := createRandomMatrix(size) duration := measurePerformance(fmt.Sprintf( "ćµć¤ćŗ %d" , size), func () { matrixMultiplication(a, b, size) }) if i > 0 { ratio := float64 (duration) / float64 (prevDuration) theoretical := float64 (size*size*size) / float64 (sizes[i- 1 ]*sizes[i- 1 ]*sizes[i- 1 ]) fmt.Printf( " å®ęø¬ęÆē: %.2fx, ēč«å¤(n^3): %.2fx \n " , ratio, theoretical) } prevDuration = duration } } // ćć£ćć·ć„å¹ēć®ęÆč¼å®éØ func compareCacheEfficiency() { fmt.Println( " \n === ćć£ćć·ć„å¹ēć®ęÆč¼ ===" ) size := 1000 fmt.Println( "2ꬔå
é
åć¢ćÆć»ć¹ććæć¼ć³ć®ęÆč¼:" ) // éå¹ēćŖććæć¼ć³ļ¼ååŖå
ļ¼ measurePerformance( "ååŖå
ć¢ćÆć»ć¹ļ¼éå¹ēļ¼" , func () { basicNestedLoop(size) }) // å¹ēēćŖććæć¼ć³ļ¼č”åŖå
ļ¼ measurePerformance( "č”åŖå
ć¢ćÆć»ć¹ļ¼å¹ēēļ¼" , func () { optimizedNestedLoop(size) }) // 1ꬔå
é
åććæć¼ć³ measurePerformance( "1ꬔå
é
åļ¼ęé©ļ¼" , func () { flattenedArrayOptimization(size) }) } // č”åä¹ē®ć®ęé©åęę³ęÆč¼ func compareMatrixOptimizations() { fmt.Println( " \n === č”åä¹ē®ć®ęé©åęę³ęÆč¼ ===" ) size := 256 blockSize := 32 a := createRandomMatrix(size) b := createRandomMatrix(size) fmt.Printf( "č”åćµć¤ćŗ: %dx%d \n " , size, size) // ęØęŗēćŖå®č£
measurePerformance( "ęØęŗå®č£
(i-j-k)" , func () { matrixMultiplication(a, b, size) }) // ć«ć¼ćé åŗęé©å measurePerformance( "ć«ć¼ćé åŗęé©å (i-k-j)" , func () { optimizedMatrixMultiplication(a, b, size) }) // ććććÆå measurePerformance( "ććććÆå" , func () { blockedMatrixMultiplication(a, b, size, blockSize) }) // äø¦åå measurePerformance( "äø¦åå" , func () { parallelMatrixMultiplication(a, b, size) }) } // ć©ć³ćć ćŖč”åćēę func createRandomMatrix(size int ) [][] int { matrix := make ([][] int , size) for i := range matrix { matrix[i] = make ([] int , size) for j := range matrix[i] { matrix[i][j] = rand.Intn( 100 ) } } return matrix } // miné¢ę°ļ¼Go 1.21ęŖęŗć§ć®äŗęę§ļ¼ func min(a, b int ) int { if a < b { return a } return b } // ęé©åć®ćć¹ććć©ćÆćć£ć¹č§£čŖ¬ func explainOptimizationPrinciples() { fmt.Println( " \n === ćć¹ćć«ć¼ćęé©åć®åå ===" ) fmt.Println( "1. ęéčØē®éć®ēč§£:" ) fmt.Println( " - O(n): ē·å½¢ęé" ) fmt.Println( " - O(n^2): 2éć«ć¼ć - ćć¼ćæćµć¤ćŗ2åć§å¦ēęé4å" ) fmt.Println( " - O(n^3): 3éć«ć¼ć - ćć¼ćæćµć¤ćŗ2åć§å¦ēęé8å" ) fmt.Println( " \n 2. ćć£ćć·ć„å¹ēć®ęé©å:" ) fmt.Println( " - CPUćć£ćć·ć„ć©ć¤ć³ļ¼éåøø64ćć¤ćļ¼ćęč" ) fmt.Println( " - é£ē¶ććć”ć¢ćŖć¢ćÆć»ć¹ćåŖå
" ) fmt.Println( " - č”åŖå
ć¢ćÆć»ć¹ļ¼row-majorļ¼ć®ę”ēØ" ) fmt.Println( " \n 3. ć«ć¼ćé åŗć®ęé©å:" ) fmt.Println( " - å
å“ć«ć¼ćć§é£ē¶ć”ć¢ćŖć¢ćÆć»ć¹" ) fmt.Println( " - äøęå¤ę°ć®ę“»ēØ" ) fmt.Println( " - äøč¦ćŖčØē®ć®å¤å“ćøć®ē§»å" ) fmt.Println( " \n 4. ćć¼ćæę§é ć®ęé©å:" ) fmt.Println( " - 2ꬔå
é
å ā 1ꬔå
é
åļ¼ćć©ććåļ¼" ) fmt.Println( " - ę§é ä½é
å ā é
åć®ę§é ä½ļ¼AoS ā SoAļ¼" ) fmt.Println( " - ć”ć¢ćŖå±ęę§ć®åäø" ) fmt.Println( " \n 5. ć¢ć«ć“ćŖćŗć ć¬ćć«ć®ę¹å:" ) fmt.Println( " - ććććÆåļ¼ćæć¤ćŖć³ć°ļ¼" ) fmt.Println( " - äø¦åå" ) fmt.Println( " - čØē®éć®åęøļ¼O(n^3) ā O(n^2.8)ćŖć©ļ¼" ) } func main() { fmt.Println( "=== ę·±ććć¹ćć«ć¼ćå¦ēć®č² č·åęćØęé©å === \n " ) // ć©ć³ćć ć·ć¼ććčØå® rand.Seed(time.Now().UnixNano()) // 1. ć”ć¢ćŖć¢ćÆć»ć¹ććæć¼ć³ć®åę analyzeMemoryAccessPatterns() // 2. čØē®éć®å®čؼå®éØ demonstrateComplexityGrowth() // 3. ćć£ćć·ć„å¹ēć®ęÆč¼ compareCacheEfficiency() // 4. č”åä¹ē®ć®ęé©åęÆč¼ compareMatrixOptimizations() // 5. ęé©åååć®č§£čŖ¬ explainOptimizationPrinciples() } å®č”ēµę === ę·±ććć¹ćć«ć¼ćå¦ēć®č² č·åęćØęé©å === === ć”ć¢ćŖć¢ćÆć»ć¹ććæć¼ć³ć®åę === 2ꬔå
ć¹ć©ć¤ć¹ć®ć”ć¢ćŖć¬ć¤ć¢ć¦ćåę: dataé
åć®ć¢ćć¬ć¹: 0x40000b8008 data[0]ć®ć¢ćć¬ć¹: 0x40000be000 data[1]ć®ć¢ćć¬ć¹: 0x40000c0000 åć®č”ćØć®å·®: 8192 ćć¤ć data[2]ć®ć¢ćć¬ć¹: 0x40000c2000 åć®č”ćØć®å·®: 8192 ćć¤ć 1ꬔå
ć¹ć©ć¤ć¹ć®ć”ć¢ćŖć¬ć¤ć¢ć¦ć: flatData[0]ć®ć¢ćć¬ć¹: 0x4000900000 flatData[1000]ć®ć¢ćć¬ć¹: 0x4000901f40 é£ē¶ććč¦ē“ ć®å·®: 8 ćć¤ć === čØē®éć®å®čؼå®éØ === åŗę¬ēćŖ2éć«ć¼ć O(n^2): ćµć¤ćŗ 100 : 19.416µs ćµć¤ćŗ 200 : 125.584µs å®ęø¬ęÆē: 6.47x, ēč«å¤(n^2): 4.00x ćµć¤ćŗ 400 : 1.697583ms å®ęø¬ęÆē: 13.52x, ēč«å¤(n^2): 4.00x ćµć¤ćŗ 800 : 6.607292ms å®ęø¬ęÆē: 3.89x, ēč«å¤(n^2): 4.00x č”åä¹ē® O(n^3): ćµć¤ćŗ 100 : 2.359708ms ćµć¤ćŗ 200 : 20.511333ms å®ęø¬ęÆē: 8.69x, ēč«å¤(n^3): 8.00x ćµć¤ćŗ 400 : 198.047333ms å®ęø¬ęÆē: 9.66x, ēč«å¤(n^3): 8.00x === ćć£ćć·ć„å¹ēć®ęÆč¼ === 2ꬔå
é
åć¢ćÆć»ć¹ććæć¼ć³ć®ęÆč¼: ååŖå
ć¢ćÆć»ć¹ļ¼éå¹ēļ¼ : 12.861208ms č”åŖå
ć¢ćÆć»ć¹ļ¼å¹ēēļ¼ : 1.88625ms 1ꬔå
é
åļ¼ęé©ļ¼ : 3.14025ms === č”åä¹ē®ć®ęé©åęę³ęÆč¼ === č”åćµć¤ćŗ: 256x256 ęØęŗå®č£
(i-j-k) : 44.545958ms ć«ć¼ćé åŗęé©å (i-k-j) : 23.862583ms ććććÆå : 31.418ms äø¦åå : 7.782542ms === ćć¹ćć«ć¼ćęé©åć®åå === 1. ęéčØē®éć®ēč§£: - O(n): ē·å½¢ęé - O(n^2): 2éć«ć¼ć - ćć¼ćæćµć¤ćŗ2åć§å¦ēęé4å - O(n^3): 3éć«ć¼ć - ćć¼ćæćµć¤ćŗ2åć§å¦ēęé8å 2. ćć£ćć·ć„å¹ēć®ęé©å: - CPUćć£ćć·ć„ć©ć¤ć³ļ¼éåøø64ćć¤ćļ¼ćęč - é£ē¶ććć”ć¢ćŖć¢ćÆć»ć¹ćåŖå
- č”åŖå
ć¢ćÆć»ć¹ļ¼row-majorļ¼ć®ę”ēØ 3. ć«ć¼ćé åŗć®ęé©å: - å
å“ć«ć¼ćć§é£ē¶ć”ć¢ćŖć¢ćÆć»ć¹ - äøęå¤ę°ć®ę“»ēØ - äøč¦ćŖčØē®ć®å¤å“ćøć®ē§»å 4. ćć¼ćæę§é ć®ęé©å: - 2ꬔå
é
å ā 1ꬔå
é
åļ¼ćć©ććåļ¼ - ę§é ä½é
å ā é
åć®ę§é ä½ļ¼AoS ā SoAļ¼ - ć”ć¢ćŖå±ęę§ć®åäø 5. ć¢ć«ć“ćŖćŗć ć¬ćć«ć®ę¹å: - ććććÆåļ¼ćæć¤ćŖć³ć°ļ¼ - äø¦åå - čØē®éć®åęøļ¼O(n^3) ā O(n^2.8)ćŖć©ļ¼ å¤ę¬”å
ć¹ć©ć¤ć¹ć®ć«ć¼ćå¦ēćÆč² č·ćé«ććććć©ć¼ćć³ć¹ćęŖåććć”ć§ćć ęē“ć«ć«ć¼ćå¦ēććå “åćę·±ć d ć«åƾć㦠O(n^d) ć®čØē®éćØćŖć£ć¦ćć¾ćć¾ćć ććć§ć仄äøć®ćććŖåƾēćčććććØćć§ćć¾ćć ćć£ćć·ć„å¹ēć®ę¹å č”åę¼ē®ć®ćććŖå¦ēć®å “åćÆäø¦åå¦ēćęå¹ ćć¹ćććę§é ä½ć®ć«ć¼ćå¦ē ćµć³ćć«8ļ¼å®č£
ļ¼å®č”ēµęļ¼ å®č£
package main import ( "fmt" "runtime" "strings" "time" "unsafe" ) // === åé”ć®ććę·±ććć¹ćę§é === // Level3: ęäøå±¤ - ęååć®ć¹ć©ć¤ć¹ type NestedLevel3 struct { ID int Messages [] string Metadata map [ string ] string } // Level2: äøé層 - Level3ć®ć¹ć©ć¤ć¹ type NestedLevel2 struct { GroupID string Items []NestedLevel3 Timestamp time.Time IsActive bool } // Level1: ęäøå±¤ - Level2ć®ć¹ć©ć¤ć¹ type NestedLevel1 struct { UserID string Groups []NestedLevel2 Settings map [ string ] interface {} } // === ęé©åćććå¹³å¦ćŖę§é === // ćć©ććåććććć¼ćæę§é type FlatData struct { UserIDs [] string GroupIDs [] string MessageIDs [] int Messages [] string // ć¤ć³ćććÆć¹ćć¼ćć« UserGroupStart [] int // åć¦ć¼ć¶ć¼ć®ć°ć«ć¼ćéå§ä½ē½® UserGroupEnd [] int // åć¦ć¼ć¶ć¼ć®ć°ć«ć¼ćēµäŗä½ē½® GroupMsgStart [] int // åć°ć«ć¼ćć®ć”ćć»ć¼ćøéå§ä½ē½® GroupMsgEnd [] int // åć°ć«ć¼ćć®ć”ćć»ć¼ćøēµäŗä½ē½® } // === äøéēćŖę§é ļ¼ę§é ä½é
åļ¼ === type SemiFlat struct { UserID string GroupID string MessageID int Message string } // ćć¹ććć¼ćæēę func createNestedTestData(numUsers, numGroups, numMessages int ) []NestedLevel1 { data := make ([]NestedLevel1, numUsers) for i := 0 ; i < numUsers; i++ { user := NestedLevel1{ UserID: fmt.Sprintf( "user_%d" , i), Groups: make ([]NestedLevel2, numGroups), Settings: make ( map [ string ] interface {}), } for j := 0 ; j < numGroups; j++ { group := NestedLevel2{ GroupID: fmt.Sprintf( "group_%d_%d" , i, j), Items: make ([]NestedLevel3, numMessages), Timestamp: time.Now(), IsActive: true , } for k := 0 ; k < numMessages; k++ { item := NestedLevel3{ ID: k, Messages: [] string { fmt.Sprintf( "Message %d from user %d group %d" , k, i, j), fmt.Sprintf( "Additional info %d" , k), }, Metadata: map [ string ] string { "type" : "info" , "source" : fmt.Sprintf( "user_%d" , i), }, } group.Items[k] = item } user.Groups[j] = group } data[i] = user } return data } // å¹³å¦åććććć¼ćæēę func createFlatTestData(numUsers, numGroups, numMessages int ) *FlatData { totalMessages := numUsers * numGroups * numMessages * 2 // åitemć«2ć¤ć®ć”ćć»ć¼ćø flat := &FlatData{ UserIDs: make ([] string , 0 , numUsers), GroupIDs: make ([] string , 0 , numUsers*numGroups), MessageIDs: make ([] int , 0 , totalMessages), Messages: make ([] string , 0 , totalMessages), UserGroupStart: make ([] int , numUsers), UserGroupEnd: make ([] int , numUsers), GroupMsgStart: make ([] int , numUsers*numGroups), GroupMsgEnd: make ([] int , numUsers*numGroups), } userIdx := 0 groupIdx := 0 msgIdx := 0 for i := 0 ; i < numUsers; i++ { flat.UserIDs = append (flat.UserIDs, fmt.Sprintf( "user_%d" , i)) flat.UserGroupStart[userIdx] = groupIdx for j := 0 ; j < numGroups; j++ { flat.GroupIDs = append (flat.GroupIDs, fmt.Sprintf( "group_%d_%d" , i, j)) flat.GroupMsgStart[groupIdx] = msgIdx for k := 0 ; k < numMessages; k++ { // 2ć¤ć®ć”ćć»ć¼ćøćčæ½å flat.MessageIDs = append (flat.MessageIDs, k, k) flat.Messages = append (flat.Messages, fmt.Sprintf( "Message %d from user %d group %d" , k, i, j), fmt.Sprintf( "Additional info %d" , k)) msgIdx += 2 } flat.GroupMsgEnd[groupIdx] = msgIdx groupIdx++ } flat.UserGroupEnd[userIdx] = groupIdx userIdx++ } return flat } // === ććć©ć¼ćć³ć¹ęø¬å® === // 1. ćć¹ćę§é ć§ć®ę¤ē“¢å¦ē func searchInNestedStructure(data []NestedLevel1, searchTerm string ) [] string { var results [] string for _, user := range data { for _, group := range user.Groups { for _, item := range group.Items { for _, message := range item.Messages { if strings.Contains(message, searchTerm) { results = append (results, fmt.Sprintf( "User: %s, Group: %s, Message: %s" , user.UserID, group.GroupID, message)) } } } } } return results } // 2. å¹³å¦åćććę§é ć§ć®ę¤ē“¢å¦ē func searchInFlatStructure(data *FlatData, searchTerm string ) [] string { var results [] string for i, message := range data.Messages { if strings.Contains(message, searchTerm) { // 対åæććć¦ć¼ć¶ć¼ćØć°ć«ć¼ććéå¼ć userIdx := findUserForMessage(data, i) groupIdx := findGroupForMessage(data, i) results = append (results, fmt.Sprintf( "User: %s, Group: %s, Message: %s" , data.UserIDs[userIdx], data.GroupIDs[groupIdx], message)) } } return results } // ć”ćć»ć¼ćøć¤ć³ćććÆć¹ććć¦ć¼ć¶ć¼ćē¹å® func findUserForMessage(data *FlatData, msgIdx int ) int { for i := 0 ; i < len (data.UserGroupStart); i++ { start := data.UserGroupStart[i] end := data.UserGroupEnd[i] for j := start; j < end; j++ { if msgIdx >= data.GroupMsgStart[j] && msgIdx < data.GroupMsgEnd[j] { return i } } } return - 1 } // ć”ćć»ć¼ćøć¤ć³ćććÆć¹ććć°ć«ć¼ććē¹å® func findGroupForMessage(data *FlatData, msgIdx int ) int { for i := 0 ; i < len (data.GroupMsgStart); i++ { if msgIdx >= data.GroupMsgStart[i] && msgIdx < data.GroupMsgEnd[i] { return i } } return - 1 } // 3. ć”ć¢ćŖć¢ćÆć»ć¹ććæć¼ć³ć®åę func analyzeMemoryLayout() { fmt.Println( "=== ć”ć¢ćŖć¬ć¤ć¢ć¦ćåę ===" ) // å°ććŖćµć³ćć«ć§ć”ć¢ćŖé
ē½®ćē¢ŗčŖ nested := createNestedTestData( 2 , 2 , 2 ) fmt.Println( "ćć¹ćę§é ć®ć”ć¢ćŖé
ē½®:" ) fmt.Printf( "nested[0]ć®ć¢ćć¬ć¹: 0x%x \n " , uintptr ( unsafe.Pointer (&nested[ 0 ]))) fmt.Printf( "nested[0].Groups[0]ć®ć¢ćć¬ć¹: 0x%x \n " , uintptr ( unsafe.Pointer (&nested[ 0 ].Groups[ 0 ]))) fmt.Printf( "nested[0].Groups[0].Items[0]ć®ć¢ćć¬ć¹: 0x%x \n " , uintptr ( unsafe.Pointer (&nested[ 0 ].Groups[ 0 ].Items[ 0 ]))) // ćć¤ć³ćæć®ę·±ććē¢ŗčŖ level1Addr := uintptr ( unsafe.Pointer (&nested[ 0 ])) groupsAddr := uintptr ( unsafe.Pointer (&nested[ 0 ].Groups[ 0 ])) itemsAddr := uintptr ( unsafe.Pointer (&nested[ 0 ].Groups[ 0 ].Items[ 0 ])) fmt.Printf( "Level1 ā Groups: %d ćć¤ćå·® \n " , groupsAddr-level1Addr) fmt.Printf( "Groups ā Items: %d ćć¤ćå·® \n " , itemsAddr-groupsAddr) // ć¹ć©ć¤ć¹ć®é
åé åć®ć¢ćć¬ć¹ if len (nested[ 0 ].Groups) > 0 && len (nested[ 0 ].Groups[ 0 ].Items) > 0 { fmt.Printf( "Groupsé
åć®å®ćć¼ćæ: 0x%x \n " , uintptr ( unsafe.Pointer (&nested[ 0 ].Groups[ 0 ]))) fmt.Printf( "Itemsé
åć®å®ćć¼ćæ: 0x%x \n " , uintptr ( unsafe.Pointer (&nested[ 0 ].Groups[ 0 ].Items[ 0 ]))) } // ćć©ććę§é ć®ē¢ŗčŖ flat := createFlatTestData( 2 , 2 , 2 ) fmt.Println( " \n ćć©ććę§é ć®ć”ć¢ćŖé
ē½®:" ) fmt.Printf( "Messagesé
åć®éå§: 0x%x \n " , uintptr ( unsafe.Pointer (&flat.Messages[ 0 ]))) if len (flat.Messages) > 1 { fmt.Printf( "Messages[1]ć®ć¢ćć¬ć¹: 0x%x \n " , uintptr ( unsafe.Pointer (&flat.Messages[ 1 ]))) fmt.Printf( "é£ē¶č¦ē“ ć®å·®: %d ćć¤ć \n " , uintptr ( unsafe.Pointer (&flat.Messages[ 1 ]))- uintptr ( unsafe.Pointer (&flat.Messages[ 0 ]))) } } // 4. ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³ćøć®å½±éæęø¬å® func measureGCImpact() { fmt.Println( " \n === ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³å½±éæęø¬å® ===" ) runtime.GC() var m1 runtime.MemStats runtime.ReadMemStats(&m1) // ćć¹ćę§é ć®ćć¼ćæä½ę fmt.Println( "ćć¹ćę§é ćć¼ćæä½ę..." ) nested := createNestedTestData( 100 , 10 , 10 ) runtime.GC() var m2 runtime.MemStats runtime.ReadMemStats(&m2) fmt.Printf( "ćć¹ćę§é ć”ć¢ćŖä½æēØé: %.2f MB \n " , float64 (m2.Alloc-m1.Alloc)/ 1024 / 1024 ) fmt.Printf( "ćć¹ćę§é ćŖććøć§ćÆćę°å¢å : %d \n " , m2.HeapObjects-m1.HeapObjects) // ćć©ććę§é ć®ćć¼ćæä½ę fmt.Println( "ćć©ććę§é ćć¼ćæä½ę..." ) flat := createFlatTestData( 100 , 10 , 10 ) runtime.GC() var m3 runtime.MemStats runtime.ReadMemStats(&m3) fmt.Printf( "ćć©ććę§é ć”ć¢ćŖä½æēØé: %.2f MB \n " , float64 (m3.Alloc-m2.Alloc)/ 1024 / 1024 ) fmt.Printf( "ćć©ććę§é ćŖććøć§ćÆćę°å¢å : %d \n " , m3.HeapObjects-m2.HeapObjects) // 使ēØéćē¶ęćć¦GCęéćęø¬å® _ = nested _ = flat } // 5. ćć£ćć·ć„ćć¹åę func analyzeCacheMisses() { fmt.Println( " \n === ćć£ćć·ć„ćć¹åę ===" ) sizes := [] struct { users, groups, messages int }{ { 10 , 5 , 5 }, { 50 , 10 , 10 }, { 100 , 20 , 20 }, } for _, size := range sizes { fmt.Printf( " \n ćć¼ćæćµć¤ćŗ: %d users, %d groups, %d messages \n " , size.users, size.groups, size.messages) nested := createNestedTestData(size.users, size.groups, size.messages) flat := createFlatTestData(size.users, size.groups, size.messages) // ćć¹ćę§é ć§ć®ę¤ē“¢ start := time.Now() nestedResults := searchInNestedStructure(nested, "Message 1" ) nestedDuration := time.Since(start) // ćć©ććę§é ć§ć®ę¤ē“¢ start = time.Now() flatResults := searchInFlatStructure(flat, "Message 1" ) flatDuration := time.Since(start) fmt.Printf( "ćć¹ćę§é : %v (%dä»¶) \n " , nestedDuration, len (nestedResults)) fmt.Printf( "ćć©ććę§é : %v (%dä»¶) \n " , flatDuration, len (flatResults)) fmt.Printf( "ę¹åē: %.2fx \n " , float64 (nestedDuration)/ float64 (flatDuration)) } } // ęé©åę¦ē„ć®č§£čŖ¬ func explainOptimizationStrategies() { fmt.Println( " \n === ćć¹ćę§é ęé©åę¦ē„ ===" ) fmt.Println( "1. åé”ē¹ć®åę:" ) fmt.Println( " ā ćć¤ć³ćæćć§ć¼ć³ć«ćććć£ćć·ć„ćć¹" ) fmt.Println( " ā ć”ć¢ćŖęēå" ) fmt.Println( " ā ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³ćŖć¼ćć¼ććć" ) fmt.Println( " ā éę„åē
§ć³ć¹ć" ) fmt.Println( " \n 2. ęé©åęę³:" ) fmt.Println( " ā
ćć¼ćæćć©ććåļ¼Structure of Arraysļ¼" ) fmt.Println( " ā
ć¤ć³ćććÆć¹ćć¼ćć«ć®ę“»ēØ" ) fmt.Println( " ā
ć”ć¢ćŖćć¼ć«ć®ä½æēØ" ) fmt.Println( " ā
ćć£ćć·ć„ćć¬ć³ććŖć¼ćŖć¢ćÆć»ć¹ććæć¼ć³" ) fmt.Println( " \n 3. é©ēØę¦ē„:" ) fmt.Println( " - čŖćæåćå°ēØćć¼ćæ ā å®å
Øćć©ććå" ) fmt.Println( " - ę“ę°é »åŗ¦ć®é«ććć¼ćæ ā éØåēćć©ććå" ) fmt.Println( " - å°č¦ęØ”ćć¼ćæ ā ęé©åäøč¦" ) fmt.Println( " - 大č¦ęØ”ćć¼ćæ ā ē©ę„µēęé©å" ) } func measurePerformance(name string , fn func ()) time.Duration { runtime.GC() start := time.Now() fn() duration := time.Since(start) fmt.Printf( "%-25s: %v \n " , name, duration) return duration } func main() { fmt.Println( "=== ę·±ććć¹ćę§é ć§ć®č² č·åęćØęé©å === \n " ) // 1. ć”ć¢ćŖć¬ć¤ć¢ć¦ćåę analyzeMemoryLayout() // 2. ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³å½±éæęø¬å® measureGCImpact() // 3. ćć£ćć·ć„ćć¹åę analyzeCacheMisses() // 4. ęé©åę¦ē„解説 explainOptimizationStrategies() } å®č”ēµę === ę·±ććć¹ćę§é ć§ć®č² č·åęćØęé©å === === ć”ć¢ćŖć¬ć¤ć¢ć¦ćåę === ćć¹ćę§é ć®ć”ć¢ćŖé
ē½®: nested[0]ć®ć¢ćć¬ć¹: 0x40000a8120 nested[0].Groups[0]ć®ć¢ćć¬ć¹: 0x40000b4000 nested[0].Groups[0].Items[0]ć®ć¢ćć¬ć¹: 0x40000b6000 Level1 ā Groups: 48864 ćć¤ćå·® Groups ā Items: 8192 ćć¤ćå·® Groupsé
åć®å®ćć¼ćæ: 0x40000b4000 Itemsé
åć®å®ćć¼ćæ: 0x40000b6000 ćć©ććę§é ć®ć”ć¢ćŖé
ē½®: Messagesé
åć®éå§: 0x40000c2000 Messages[1]ć®ć¢ćć¬ć¹: 0x40000c2010 é£ē¶č¦ē“ ć®å·®: 16 ćć¤ć === ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³å½±éæęø¬å® === ćć¹ćę§é ćć¼ćæä½ę... ćć¹ćę§é ć”ć¢ćŖä½æēØé: 0.02 MB ćć¹ćę§é ćŖććøć§ćÆćę°å¢å : 24 ćć©ććę§é ćć¼ćæä½ę... ćć©ććę§é ć”ć¢ćŖä½æēØé: 17592186044416.00 MB ćć©ććę§é ćŖććøć§ćÆćę°å¢å : 18446744073709551613 === ćć£ćć·ć„ćć¹åę === ćć¼ćæćµć¤ćŗ: 10 users, 5 groups, 5 messages ćć¹ćę§é : 16.292µs (50ä»¶) ćć©ććę§é : 14.417µs (50ä»¶) ę¹åē: 1.13x ćć¼ćæćµć¤ćŗ: 50 users, 10 groups, 10 messages ćć¹ćę§é : 163.75µs (500ä»¶) ćć©ććę§é : 346.292µs (500ä»¶) ę¹åē: 0.47x ćć¼ćæćµć¤ćŗ: 100 users, 20 groups, 20 messages ćć¹ćę§é : 5.604417ms (22000ä»¶) ćć©ććę§é : 36.147542ms (22000ä»¶) ę¹åē: 0.16x === ćć¹ćę§é ęé©åę¦ē„ === 1. åé”ē¹ć®åę: ā ćć¤ć³ćæćć§ć¼ć³ć«ćććć£ćć·ć„ćć¹ ā ć”ć¢ćŖęēå ā ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³ćŖć¼ćć¼ććć ā éę„åē
§ć³ć¹ć 2. ęé©åęę³: ā
ćć¼ćæćć©ććåļ¼Structure of Arraysļ¼ ā
ć¤ć³ćććÆć¹ćć¼ćć«ć®ę“»ēØ ā
ć”ć¢ćŖćć¼ć«ć®ä½æēØ ā
ćć£ćć·ć„ćć¬ć³ććŖć¼ćŖć¢ćÆć»ć¹ććæć¼ć³ 3. é©ēØę¦ē„: - čŖćæåćå°ēØćć¼ćæ ā å®å
Øćć©ććå - ę“ę°é »åŗ¦ć®é«ććć¼ćæ ā éØåēćć©ććå - å°č¦ęØ”ćć¼ćæ ā ęé©åäøč¦ - 大č¦ęØ”ćć¼ćæ ā ē©ę„µēęé©å ę§é ä½ćÆć”ć¢ćŖć®ē¢ŗäæé åć大ććå²ćå½ć¦ćććć”ć¢ćŖé åćé¢ćć¦ćć¾ćććć ćć®ć¾ć¾ć§ćÆćć£ćć·ć„å¹ēć®ę¹åćÆé£ćććØčćććć¾ćć ć¾ćććć£ć¼ć«ćć«ćę§é ä½ćęć¤å “åćÆćććć¾ć§ć«č¦ć¦ććććć«å¦ēč² č·ćé«ććŖć£ć¦ćć¾ćć¾ćć ćć®ćććŖē¶ę³ć§ćÆćé©åćŖäøéę§é ä½ćå®ē¾©ć㦠éØåēć«ćć©ććåććććØć§ćć£ćć·ć„å¹ēć®ę¹åćå³ćććØć対ēćØćć¦čćććć¾ćć ä»ć«ććć”ć¢ćŖćć¼ć«ćå©ēØććå¹ēåćęå¹ćŖå “åćććć¾ćć ć”ć¢ćŖćć¼ć«ć®ę“»ēØ ćµć³ćć«9ļ¼å®č£
ļ¼å®č”ēµęļ¼ å®č£
package main import ( "fmt" "runtime" "strings" "sync" "time" ) // === å¾ę„ć®ćŖććøć§ćÆćēęććæć¼ć³ļ¼åé”ć®ććę¹ę³ļ¼ === type ExpensiveStruct struct { ID int Name string Data [] byte Children []*ExpensiveStruct Metadata map [ string ] interface {} } // å¾ę„ć®ę¹ę³ļ¼ęÆåę°ćććŖććøć§ćÆććēę func createExpensiveStructTraditional() *ExpensiveStruct { return &ExpensiveStruct{ Data: make ([] byte , 1024 ), Children: make ([]*ExpensiveStruct, 10 ), Metadata: make ( map [ string ] interface {}), } } // === sync.Poolć使ēØććć”ć¢ćŖćć¼ć« === var expensiveStructPool = sync.Pool{ New: func () interface {} { fmt.Println( " [ćć¼ć«] ę°ćććŖććøć§ćÆććä½ę" ) return &ExpensiveStruct{ Data: make ([] byte , 1024 ), Children: make ([]*ExpensiveStruct, 10 ), Metadata: make ( map [ string ] interface {}), } }, } // ćć¼ć«ćććŖććøć§ćÆććåå¾ func getExpensiveStructFromPool() *ExpensiveStruct { obj := expensiveStructPool.Get().(*ExpensiveStruct) // ćŖććøć§ćÆćććŖć»ćć obj.ID = 0 obj.Name = "" obj.Data = obj.Data[: 0 ] for i := range obj.Children { obj.Children[i] = nil } for k := range obj.Metadata { delete (obj.Metadata, k) } return obj } // ćć¼ć«ć«ćŖććøć§ćÆććčæå“ func putExpensiveStructToPool(obj *ExpensiveStruct) { expensiveStructPool.Put(obj) } // === ć«ć¹ćæć ć”ć¢ćŖćć¼ć«ļ¼ććé«åŗ¦ćŖå¶å¾”ļ¼ === type CustomMemoryPool struct { objects chan *ExpensiveStruct newFunc func () *ExpensiveStruct resetFunc func (*ExpensiveStruct) maxSize int created int64 reused int64 mu sync.Mutex } func NewCustomMemoryPool(maxSize int ) *CustomMemoryPool { return &CustomMemoryPool{ objects: make ( chan *ExpensiveStruct, maxSize), newFunc: func () *ExpensiveStruct { return &ExpensiveStruct{ Data: make ([] byte , 1024 ), Children: make ([]*ExpensiveStruct, 10 ), Metadata: make ( map [ string ] interface {}), } }, resetFunc: func (obj *ExpensiveStruct) { obj.ID = 0 obj.Name = "" obj.Data = obj.Data[: 0 ] for i := range obj.Children { obj.Children[i] = nil } for k := range obj.Metadata { delete (obj.Metadata, k) } }, maxSize: maxSize, } } func (p *CustomMemoryPool) Get() *ExpensiveStruct { select { case obj := <-p.objects: p.mu.Lock() p.reused++ p.mu.Unlock() p.resetFunc(obj) return obj default : p.mu.Lock() p.created++ p.mu.Unlock() return p.newFunc() } } func (p *CustomMemoryPool) Put(obj *ExpensiveStruct) { select { case p.objects <- obj: // ę£åøøć«ćć¼ć«ć«čæå“ default : // ćć¼ć«ćęŗęÆć®å “åćÆē “ę£ } } func (p *CustomMemoryPool) Stats() (created, reused int64 ) { p.mu.Lock() defer p.mu.Unlock() return p.created, p.reused } // === ć¹ć©ć¤ć¹å°ēØćć¼ć« === var byteSlicePool = sync.Pool{ New: func () interface {} { fmt.Println( " [ć¹ć©ć¤ć¹ćć¼ć«] ę°ććć¹ć©ć¤ć¹ćä½ę" ) return make ([] byte , 0 , 1024 ) }, } func getByteSliceFromPool() [] byte { return byteSlicePool.Get().([] byte )[: 0 ] } func putByteSliceToPool(slice [] byte ) { if cap (slice) <= 1024 * 10 { // 容éå¶é byteSlicePool.Put(slice) } } // === ćććć”ćć¼ć«ļ¼strings.BuilderēØļ¼ === var builderPool = sync.Pool{ New: func () interface {} { return &strings.Builder{} }, } func getBuilderFromPool() *strings.Builder { return builderPool.Get().(*strings.Builder) } func putBuilderToPool(b *strings.Builder) { b.Reset() builderPool.Put(b) } // === ććć©ć¼ćć³ć¹ęø¬å® === func measureTraditionalApproach(iterations int ) time.Duration { start := time.Now() for i := 0 ; i < iterations; i++ { obj := createExpensiveStructTraditional() obj.ID = i obj.Name = fmt.Sprintf( "Object_%d" , i) obj.Data = append (obj.Data, byte (i% 256 )) obj.Metadata[ "iteration" ] = i // 使ēØå¾ćÆGCć«ä»»ććļ¼ä½ćććŖćļ¼ _ = obj } return time.Since(start) } func measureSyncPoolApproach(iterations int ) time.Duration { start := time.Now() for i := 0 ; i < iterations; i++ { obj := getExpensiveStructFromPool() obj.ID = i obj.Name = fmt.Sprintf( "Object_%d" , i) obj.Data = append (obj.Data, byte (i% 256 )) obj.Metadata[ "iteration" ] = i // ćć¼ć«ć«čæå“ putExpensiveStructToPool(obj) } return time.Since(start) } func measureCustomPoolApproach(pool *CustomMemoryPool, iterations int ) time.Duration { start := time.Now() for i := 0 ; i < iterations; i++ { obj := pool.Get() obj.ID = i obj.Name = fmt.Sprintf( "Object_%d" , i) obj.Data = append (obj.Data, byte (i% 256 )) obj.Metadata[ "iteration" ] = i // ćć¼ć«ć«čæå“ pool.Put(obj) } return time.Since(start) } // === GCč² č·ć®ęø¬å® === func measureGCImpact() { fmt.Println( "=== ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³č² č·ęø¬å® ===" ) iterations := 100000 // å¾ę„ć®ę¹ę³ runtime.GC() var m1 runtime.MemStats runtime.ReadMemStats(&m1) fmt.Println( "1. å¾ę„ć®ę¹ę³ļ¼ęÆåę°č¦ä½ęļ¼" ) traditionalTime := measureTraditionalApproach(iterations) runtime.GC() var m2 runtime.MemStats runtime.ReadMemStats(&m2) fmt.Printf( " ęé: %v \n " , traditionalTime) fmt.Printf( " GCåę°: %d \n " , m2.NumGC-m1.NumGC) fmt.Printf( " ć”ć¢ćŖä½æēØé: %.2f MB \n " , float64 (m2.Alloc)/ 1024 / 1024 ) fmt.Printf( " 瓯čØå²ćå½ć¦: %.2f MB \n " , float64 (m2.TotalAlloc-m1.TotalAlloc)/ 1024 / 1024 ) // sync.Poolä½æēØ fmt.Println( " \n 2. sync.Pool使ēØ" ) syncPoolTime := measureSyncPoolApproach(iterations) runtime.GC() var m3 runtime.MemStats runtime.ReadMemStats(&m3) fmt.Printf( " ęé: %v \n " , syncPoolTime) fmt.Printf( " GCåę°: %d \n " , m3.NumGC-m2.NumGC) fmt.Printf( " ć”ć¢ćŖä½æēØé: %.2f MB \n " , float64 (m3.Alloc)/ 1024 / 1024 ) fmt.Printf( " 瓯čØå²ćå½ć¦: %.2f MB \n " , float64 (m3.TotalAlloc-m2.TotalAlloc)/ 1024 / 1024 ) // ć«ć¹ćæć ćć¼ć«ä½æēØ customPool := NewCustomMemoryPool( 100 ) fmt.Println( " \n 3. ć«ć¹ćæć ćć¼ć«ä½æēØ" ) customPoolTime := measureCustomPoolApproach(customPool, iterations) runtime.GC() var m4 runtime.MemStats runtime.ReadMemStats(&m4) created, reused := customPool.Stats() fmt.Printf( " ęé: %v \n " , customPoolTime) fmt.Printf( " GCåę°: %d \n " , m4.NumGC-m3.NumGC) fmt.Printf( " ć”ć¢ćŖä½æēØé: %.2f MB \n " , float64 (m4.Alloc)/ 1024 / 1024 ) fmt.Printf( " 瓯čØå²ćå½ć¦: %.2f MB \n " , float64 (m4.TotalAlloc-m3.TotalAlloc)/ 1024 / 1024 ) fmt.Printf( " ę°č¦ä½ę: %d, åå©ēØ: %d (åå©ēØē: %.1f%%) \n " , created, reused, float64 (reused)/ float64 (created+reused)* 100 ) // ēµęęÆč¼ fmt.Println( " \n === ććć©ć¼ćć³ć¹ęÆč¼ ===" ) fmt.Printf( "sync.Poolę¹åē: %.2fxéć \n " , float64 (traditionalTime)/ float64 (syncPoolTime)) fmt.Printf( "ć«ć¹ćæć ćć¼ć«ę¹åē: %.2fxéć \n " , float64 (traditionalTime)/ float64 (customPoolTime)) } // === å®éć®ć¦ć¼ć¹ć±ć¼ć¹: JSONå¦ēć§ć®ę“»ēØ === type JSONProcessor struct { builderPool sync.Pool bufferPool sync.Pool } func NewJSONProcessor() *JSONProcessor { return &JSONProcessor{ builderPool: sync.Pool{ New: func () interface {} { return &strings.Builder{} }, }, bufferPool: sync.Pool{ New: func () interface {} { return make ([] byte , 0 , 1024 ) }, }, } } func (jp *JSONProcessor) ProcessWithPool(data [] map [ string ] interface {}) string { builder := jp.builderPool.Get().(*strings.Builder) buffer := jp.bufferPool.Get().([] byte ) defer func () { builder.Reset() jp.builderPool.Put(builder) jp.bufferPool.Put(buffer[: 0 ]) }() builder.WriteString( "[" ) for i, item := range data { if i > 0 { builder.WriteString( "," ) } builder.WriteString(fmt.Sprintf( `{"id":%v,"name":"%v"}` , item[ "id" ], item[ "name" ])) } builder.WriteString( "]" ) return builder.String() } func (jp *JSONProcessor) ProcessWithoutPool(data [] map [ string ] interface {}) string { var builder strings.Builder builder.WriteString( "[" ) for i, item := range data { if i > 0 { builder.WriteString( "," ) } builder.WriteString(fmt.Sprintf( `{"id":%v,"name":"%v"}` , item[ "id" ], item[ "name" ])) } builder.WriteString( "]" ) return builder.String() } // ćć¼ć«ć®å¹ęēćŖä½æēØććæć¼ć³ć®ć㢠func demonstratePoolPatterns() { fmt.Println( " \n === ćć¼ć«ä½æēØććæć¼ć³ć®ć㢠===" ) // ććæć¼ć³1: é«é »åŗ¦ćŖå¦ē fmt.Println( "1. é«é »åŗ¦ćŖJSONå¦ēć§ć®å¹ę" ) processor := NewJSONProcessor() testData := make ([] map [ string ] interface {}, 1000 ) for i := range testData { testData[i] = map [ string ] interface {}{ "id" : i, "name" : fmt.Sprintf( "Item_%d" , i), } } // ćć¼ć«ćŖć start := time.Now() for i := 0 ; i < 1000 ; i++ { _ = processor.ProcessWithoutPool(testData[: 10 ]) } withoutPoolTime := time.Since(start) // ćć¼ć«ćć start = time.Now() for i := 0 ; i < 1000 ; i++ { _ = processor.ProcessWithPool(testData[: 10 ]) } withPoolTime := time.Since(start) fmt.Printf( " ćć¼ć«ćŖć: %v \n " , withoutPoolTime) fmt.Printf( " ćć¼ć«ćć: %v \n " , withPoolTime) fmt.Printf( " ę¹åē: %.2fx \n " , float64 (withoutPoolTime)/ float64 (withPoolTime)) } // ć”ć¢ćŖćć¼ć«ć®ćć¹ććć©ćÆćć£ć¹ func explainBestPractices() { fmt.Println( " \n === ć”ć¢ćŖćć¼ć«ć®ćć¹ććć©ćÆćć£ć¹ ===" ) fmt.Println( "1. sync.Poolć®ē¹å¾“:" ) fmt.Println( " ā
čŖåēćŖćµć¤ćŗčŖæę“" ) fmt.Println( " ā
GCęć®čŖåćÆćŖć¢" ) fmt.Println( " ā
ć¹ć¬ććć»ć¼ć" ) fmt.Println( " ā ļø ćŖććøć§ćÆćć®ēåäæčؼćŖć" ) fmt.Println( " \n 2. ć«ć¹ćæć ćć¼ć«ć®ē¹å¾“:" ) fmt.Println( " ā
å®å
ØćŖå¶å¾”" ) fmt.Println( " ā
ēµ±čØę
å ±ć®åå¾" ) fmt.Println( " ā
ćŖććøć§ćÆćć®ēåäæčؼ" ) fmt.Println( " ā ļø ęåć§ć®ćµć¤ćŗē®”ē" ) fmt.Println( " \n 3. 使ćåćć®ęé:" ) fmt.Println( " - äøęēćŖćŖććøć§ćÆć ā sync.Pool" ) fmt.Println( " - éč¦ćŖćŖććøć§ćÆć ā ć«ć¹ćæć ćć¼ć«" ) fmt.Println( " - é«é »åŗ¦å¦ē ā åæ
é " ) fmt.Println( " - ä½é »åŗ¦å¦ē ā äøč¦" ) fmt.Println( " \n 4. 注ęē¹:" ) fmt.Println( " ā ćŖććøć§ćÆćć®ē¶ę
ććÆćŖć¢ćåæć" ) fmt.Println( " ā ćć¼ć«ćµć¤ćŗć®čØå®ćć¹" ) fmt.Println( " ā čæå“ćåæć" ) fmt.Println( " ā éåŗ¦ćŖęé©å" ) } func main() { fmt.Println( "=== ć”ć¢ćŖćć¼ć«ć«ććé«éåå¦ēæ === \n " ) // 1. GCč² č·ćØććć©ć¼ćć³ć¹ć®ęø¬å® measureGCImpact() // 2. å®éć®ć¦ć¼ć¹ć±ć¼ć¹ć§ć®ć㢠demonstratePoolPatterns() // 3. ćć¹ććć©ćÆćć£ć¹ć®č§£čŖ¬ explainBestPractices() } å®č”ēµę === ć”ć¢ćŖćć¼ć«ć«ććé«éåå¦ēæ === === ć¬ćć¼ćøć³ć¬ćÆć·ć§ć³č² č·ęø¬å® === 1. å¾ę„ć®ę¹ę³ļ¼ęÆåę°č¦ä½ęļ¼ ęé: 66.5715ms GCåę°: 88 ć”ć¢ćŖä½æēØé: 0.12 MB 瓯čØå²ćå½ć¦: 287.00 MB 2. sync.Poolä½æēØ [ćć¼ć«] ę°ćććŖććøć§ćÆććä½ę ęé: 10.777625ms GCåę°: 2 ć”ć¢ćŖä½æēØé: 0.13 MB 瓯čØå²ćå½ć¦: 3.06 MB 3. ć«ć¹ćæć ćć¼ć«ä½æēØ ęé: 12.89925ms GCåę°: 2 ć”ć¢ćŖä½æēØé: 0.13 MB 瓯čØå²ćå½ć¦: 3.05 MB ę°č¦ä½ę: 1, åå©ēØ: 99999 (åå©ēØē: 100.0%) === ććć©ć¼ćć³ć¹ęÆč¼ === sync.Poolę¹åē: 6.18xéć ć«ć¹ćæć ćć¼ć«ę¹åē: 5.16xéć === ćć¼ć«ä½æēØććæć¼ć³ć®ć㢠=== 1. é«é »åŗ¦ćŖJSONå¦ēć§ć®å¹ę ćć¼ć«ćŖć: 988µs ćć¼ć«ćć: 1.265667ms ę¹åē: 0.78x === ć”ć¢ćŖćć¼ć«ć®ćć¹ććć©ćÆćć£ć¹ === 1. sync.Poolć®ē¹å¾“: ā
čŖåēćŖćµć¤ćŗčŖæę“ ā
GCęć®čŖåćÆćŖć¢ ā
ć¹ć¬ććć»ć¼ć ā ļø ćŖććøć§ćÆćć®ēåäæčؼćŖć 2. ć«ć¹ćæć ćć¼ć«ć®ē¹å¾“: ā
å®å
ØćŖå¶å¾” ā
ēµ±čØę
å ±ć®åå¾ ā
ćŖććøć§ćÆćć®ēåäæčؼ ā ļø ęåć§ć®ćµć¤ćŗē®”ē 3. 使ćåćć®ęé: - äøęēćŖćŖććøć§ćÆć ā sync.Pool - éč¦ćŖćŖććøć§ćÆć ā ć«ć¹ćæć ćć¼ć« - é«é »åŗ¦å¦ē ā åæ
é - ä½é »åŗ¦å¦ē ā äøč¦ 4. 注ęē¹: ā ćŖććøć§ćÆćć®ē¶ę
ććÆćŖć¢ćåæć ā ćć¼ć«ćµć¤ćŗć®čØå®ćć¹ ā čæå“ćåæć ā éåŗ¦ćŖęé©å ć”ć¢ćŖćć¼ć«ćę“»ēØććććØć§ćŖććøć§ćÆćć®ä½ęļ¼ć”ć¢ćŖć®ē¢ŗäæļ¼ć1åŗ¦ć ćć«ćŖćć 仄äøć®ćććŖć”ćŖćććå¾ććć¾ćć ćŖććøć§ćÆćć®ēęļ¼åé¤ć³ć¹ććä½ććŖć ć”ć¢ćŖå²ćå½ć¦ćŖć©ć®ć·ć¹ćć ć³ć¼ć«ć1åŗ¦ććēŗēććŖć ćć¼ćæć®ę¤ē“¢ćŖć©ć®éćč¤éćŖćŖććøć§ćÆćć®ć°ć©ćć辿ćåæ
č¦ććŖćć 1ć¤ć®ćŖććøć§ćÆććč¦ćć ćć§čÆććŖć ć”ć¢ćŖć®ćć©ć°ć”ć³ćć¼ć·ć§ć³ćēŗēćć„ćććŖć ćć ććē¶ę
ć®åęåććć¼ćæć®ę ¼ē“ćé½åŗ¦å®č”ććåæ
č¦ćććććć ä½åŗ¦ćć«ć¼ćå¦ēćē¹°ćčæććććŖå “åćÆćŖć¼ćć¼ćććć®ę¹ć大ćććŖćåÆč½ę§ćććć¾ćć ęę cursor äø»å°ć«ććå¦ēæć®ä½éØćÆęć£ć¦ćććććčÆććć®ć§ććć ē¹ć«ä»„äøć®ē¹ćÆēę AI ćŖćć§ćÆć®ćć¤ć³ćć§ććŖććć¤å¦ćć å
容ć®å®ēć®å©ćć«ććŖććØęćć¾ććć ćć«ć·ćć¼ć·ć§ć³ć®åÆč½ę§ćåęćØćŖććććčŖē¶ćØčŖåććäøę¬”ę
å ±ćę¢ćććØćć§ćć ćÆć¤ćŗå½¢å¼ć«ććććØć§ć愽ććå¦ēæćé²ććććØćć§ćć ćć¼ćć«åƾćć¦1äŗŗć§éé²ć«čŖæę»ćććććå¹ēććå¦ēæćé²ćććć ćØćć£ćæć¼äøć§é²č”ćććććChatGPT ć Gemini ćŖć©ć® study mode ćććå®č£
ćØåÆ¾č©±ćć·ć¼ć ć¬ć¹ć«ćŖć ćććć« ę¬čØäŗć§ćÆćCursor ćå©ēØććå®å
Ø AI äø»å°ć§ć®å¦ēæä½éØćå
±ęćć¾ććć å¦ēæć®ēµéćčæ½ć£ć¦ććććććć«č©³ē“°ćŖćć°ćčØč¼ććć®ć§é·ććŖć£ć¦ćć¾ćć¾ćććć ēę AI ćå©ēØććå¦ēæć®é°å²ę°ćęćåć£ć¦ććć ććććØęćć¾ćć ęå¾ć¾ć§čŖćć§ććć ććććććØććććć¾ććć åč Go ć® copy ćÆććć«ćć¦å®č£
ćććć (2025.09.02 é²č¦§) slice-internals ↩ slice ę§é ä½ć®å®č£
↩ slice ć®å®¹éę”å¼µć¢ć«ć“ćŖćŗć ↩ ćµć¤ćŗćÆć©ć¹ ↩ stringStruct ę§é ä½ć®å®č£
↩