Skip to content

Commit 5d0597b

Browse files
authored
Merge pull request #709 from devlights:add-strings-clone-example
Add strings.Clone example
2 parents 6503d89 + 428a916 commit 5d0597b

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

examples/basic/strs/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@
1111
|using\_builder.go|string\_using\_builder|strings.Builder を利用したサンプルです.|
1212
|rune\_count.go|string\_rune\_count|utf8.RuneCountInString() のサンプルです.|
1313
|diff\_trimright\_trimsuffix.go|string\_diff\_trimright\_trimsuffix|strings.TrimRight と strings.TrimSuffix のちょっとした違いについてのサンプルです.|
14+
|using\_string\_clone.go|string\_using\_clone|Go 1.18 で追加された strings.Clone() のサンプルです|

examples/basic/strs/examples.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ func (r *register) Regist(m mapping.ExampleMapping) {
2121
m["string_rune_count"] = RuneCount
2222
m["string_diff_trimright_trimsuffix"] = DiffTrimRightAndTrimSuffix
2323
m["string_cut_prefix_suffix"] = CutPrefixSuffix
24+
m["string_using_clone"] = UsingStringsClone
2425
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package strs
2+
3+
import (
4+
"os/exec"
5+
"strings"
6+
7+
"github.com/devlights/gomy/output"
8+
)
9+
10+
// UsingStringsClone は、Go 1.18 で追加された strings.Clone() のサンプルです。
11+
//
12+
// # REFERENCES
13+
// - https://pkg.go.dev/strings@go1.21.4#Clone
14+
func UsingStringsClone() error {
15+
//
16+
// strings.Clone() は、Go 1.18 で追加された関数。
17+
// 新たなメモリ割り当ても行われるので、ディープコピーされるイメージ。
18+
// 部分文字列を特定のストアに対して保持するようなシチュエーションで利用できる。
19+
// (Goの標準コンパイラでは、現状元の文字列と部分文字列は同じメモリを共有するようになっているため
20+
// 数が多い、または、文字列のサイズが巨大な場合などにディープコピーしておかないとメモリが残ることなる)
21+
//
22+
23+
const (
24+
NUM_ITEMS = 100
25+
)
26+
27+
var (
28+
l = make([]string, NUM_ITEMS)
29+
)
30+
31+
// 1024バイトのランダム文字列を1000個用意
32+
for i := 0; i < NUM_ITEMS; i++ {
33+
var (
34+
c *exec.Cmd
35+
output []byte
36+
err error
37+
)
38+
39+
c = exec.Command("/bin/bash", "-c", "openssl rand -base64 1024 | tr -d '\n'")
40+
if output, err = c.Output(); err != nil {
41+
return err
42+
}
43+
44+
l[i] = string(output)
45+
}
46+
47+
//
48+
// 各文字列の先頭5文字分を識別子として保持しておく仕様があるとする
49+
//
50+
51+
var (
52+
store1 = make([]string, NUM_ITEMS)
53+
store2 = make([]string, NUM_ITEMS)
54+
)
55+
56+
// 部分文字列を取り出し、そのまま保持
57+
// この場合、元文字列と部分文字列は同じメモリを共有している可能性があるため
58+
// 場合によっては、5バイト分だけじゃなく、文字列全部がメモリに残ったままとなる
59+
for i := 0; i < NUM_ITEMS; i++ {
60+
store1[i] = l[i][:5]
61+
}
62+
63+
// 部分文字列を取り出し、クローンしてから保持
64+
// Go 1.18 で追加された strings.Clone() を利用することで、新たな割当が行われた状態で
65+
// 文字列がクローンされる。なので元文字列全部がメモリに残ることはなくなる
66+
for i := 0; i < NUM_ITEMS; i++ {
67+
store2[i] = strings.Clone(l[i][:5])
68+
}
69+
70+
for i := 0; i < 3; i++ {
71+
output.Stdoutf("[store1]", "%d: %s\n", i, store1[i])
72+
output.Stdoutf("[store2]", "%d: %s\n", i, store2[i])
73+
}
74+
75+
return nil
76+
}

0 commit comments

Comments
 (0)