strings
حزمة strings تنفذ دوال بسيطة للتعامل مع السلاسل المشفرة بـ UTF-8، وببساطة هي حزمة أدوات للتعامل مع السلاسل.
الوثائق الرسمية: strings package - strings - Go Packages
TIP
تدعم Go بشكل أصلي UTF8، وجميع عمليات السلاسل مبنية على أساس UTF8.
الاستيراد
import (
"strings"
)فيما يلي سيتم شرح الدوال الشائعة من خلال أمثلة.
نسخ سلسلة
func Clone(s string) stringستُخصص ذاكرة جديدة للنسخة المنسوخة، إذا تم تمرير سلسلة فارغة، فلن تُخصص ذاكرة وسيُرجع سلسلة فارغة.
func TestClone(t *testing.T) {
ori := "hello 世界"
copys := strings.Clone(ori)
fmt.Println(ori, copys)
fmt.Println(&ori, ©s)
}=== RUN TestClone
hello 世界 hello 世界
0xc00005e5d0 0xc00005e5e0
--- PASS: TestClone (0.00s)
PASSمقارنة السلاسل
func Compare(a, b string) intتتم مقارنة a و b حسب الترتيب المعجمي، إذا a>b تُرجع 1، وإذا a<b تُرجع -1، وإذا a=b تُرجع 0.
func TestCompare(t *testing.T) {
fmt.Println(strings.Compare("abc", "abe"))
fmt.Println(strings.Compare("abcd", "abe"))
fmt.Println(strings.Compare("abijk", "abe"))
fmt.Println(strings.Compare("abe", "abe"))
}=== RUN TestCompare
-1
-1
1
0
--- PASS: TestCompare (0.00s)
PASSاحتواء سلسلة
func Contains(s, substr string) boolللتحقق مما إذا كانت السلسلة s تحتوي على سلسلة فرعية substr
func TestContains(t *testing.T) {
fmt.Println(strings.Contains("abcdefg", "a"))
fmt.Println(strings.Contains("abcdefg", "abc"))
fmt.Println(strings.Contains("abcdefg", "ba"))
}=== RUN TestContains
true
true
false
--- PASS: TestContains (0.00s)
PASSfunc ContainsAny(s, chars string) boolللتحقق مما إذا كان أي حرف من أحرف السلسلة chars موجود في السلسلة s
func TestContainsAny(t *testing.T) {
fmt.Println(strings.ContainsAny("abcedfg", "bac"))
fmt.Println(strings.ContainsAny("abcedfg", "gfdecba"))
}=== RUN TestContainsAny
true
--- PASS: TestContainsAny (0.00s)
PASSfunc ContainsRune(s string, r rune) boolللتحقق مما إذا كانت السلسلة s تحتوي على الحرف r
func TestContainsRune(t *testing.T) {
fmt.Println(strings.ContainsRune("abcedf", 'a'))
fmt.Println(strings.ContainsRune("abcedf", 'b'))
fmt.Println(strings.ContainsRune("你好世界", '你'))
}=== RUN TestContainsRune
true
true
true
--- PASS: TestContainsRune (0.00s)
PASSعدد مرات ظهور السلسلة الفرعية
func Count(s, substr string) intتُرجع عدد مرات ظهور السلسلة الفرعية substr في السلسلة s
func TestCount(t *testing.T) {
fmt.Println(strings.Count("3.1415926", "1"))
fmt.Println(strings.Count("there is a girl", "e"))
fmt.Println(strings.Count("there is a girl", ""))
}=== RUN TestCount
2
2
16
--- PASS: TestCount (0.00s)
PASSحذف سلسلة فرعية محددة
func Cut(s, sep string) (before, after string, found bool)تحذف أول ظهور للسلسلة الفرعية sep في s، وتُرجع النتيجة بعد الحذف
before- السلسلة قبل موضع السلسلة الفرعية المحذوفةafter- السلسلة بعد موضع السلسلة الفرعية المحذوفةfound- هل تم العثور على السلسلة الفرعية
func TestCut(t *testing.T) {
show := func(s, sep string) {
before, after, found := strings.Cut(s, sep)
fmt.Printf("Cut(%q, %q) = %q, %q, %v\n", s, sep, before, after, found)
}
show("Hello world", " ")
show("Hello world", "world")
show("Hello world", "Hello")
show("Hello world", "Hello world")
}=== RUN TestCut
Cut("Hello world", " ") = "Hello", "world", true
Cut("Hello world", "world") = "Hello ", "", true
Cut("Hello world", "Hello") = "", " world", true
Cut("Hello world", "Hello world") = "", "", true
--- PASS: TestCut (0.00s)
PASSالمساواة مع تجاهل حالة الأحرف
func EqualFold(s, t string) boolتُرجع ما إذا كانت السلسلتان s و t متساويتين عند تجاهل حالة الأحرف
func TestEqualFold(t *testing.T) {
fmt.Println(strings.EqualFold("你好", "你好"))
fmt.Println(strings.EqualFold("Hello", "Hello"))
fmt.Println(strings.EqualFold("Hello", "hELLO"))
}=== RUN TestEqualFold
true
true
true
--- PASS: TestEqualFold (0.00s)
PASSتقسيم السلسلة
func Fields(s string) []stringfunc FieldsFunc(s string, f func(rune) bool) []stringالأولى تقسم السلسلة حسب المسافات، والثانية تقسم حسب القيمة المرجعة للدالة f.
func TestField(t *testing.T) {
fmt.Printf("%q\n", strings.Fields(" a b c d e f g "))
fmt.Printf("%q\n", strings.FieldsFunc("a,b,c,d,e,f,g", func(r rune) bool {
return r == ','
}))
}=== RUN TestField
["a" "b" "c" "d" "e" "f" "g"]
["a" "b" "c" "d" "e" "f" "g"]
--- PASS: TestField (0.00s)
PASSالبحث عن البادئة واللاحقة
func HasPrefix(s, prefix string) boolfunc HasSuffix(s, suffix string) boolالأولى للبحث عن البادئة، والثانية للبحث عن اللاحقة، إذا كنت مهتماً يمكنك الاطلاع على الكود المصدري هنا، فهو ذكي جداً.
func TestPreSuffix(t *testing.T) {
str := "abbc cbba"
fmt.Println(strings.HasPrefix(str, "abb"))
fmt.Println(strings.HasSuffix(str, "bba"))
}=== RUN TestPreSuffix
true
true
--- PASS: TestPreSuffix (0.00s)
PASSموضع السلسلة الفرعية
تُرجع فهرس أول ظهور للسلسلة الفرعية
func Index(s, substr string) intتُرجع فهرس أول ظهور لأي حرف من السلسلة الفرعية
func IndexAny(s, chars string) intتُرجع فهرس أول ظهور للحرف
func IndexRune(s string, r rune) intمثال
func TestIndex(t *testing.T) {
fmt.Println(strings.Index("abcdefg", "bc"))
fmt.Println(strings.IndexAny("abcdefg", "cb"))
fmt.Println(strings.IndexRune("abcdefg", 'g'))
}=== RUN TestIndex
1
1
6
--- PASS: TestIndex (0.00s)
PASSتُرجع فهرس آخر ظهور للسلسلة الفرعية
func LastIndex(s, substr string) intتُرجع فهرس آخر ظهور لأي حرف من السلسلة الفرعية
func LastIndexAny(s, chars string) intمثال
func TestLastIndex(t *testing.T) {
fmt.Println(strings.LastIndex("abcdefga", "a"))
fmt.Println(strings.LastIndexAny("abcdefghisa", "ba"))
}تكرار استبدال السلسلة
تُرجع Map نسخة من السلسلة s، وتُعدّل جميع أحرف السلسلة s حسب دالة التخطيط. إذا أعادت دالة التخطيط قيمة سالبة، يُحذف الحرف من السلسلة دون استبداله
func Map(mapping func(rune) rune, s string) stringمثال
func TestMap(t *testing.T) {
fmt.Println(strings.Map(func(r rune) rune {
return r - 32
}, "abcdefghijk"))
fmt.Println(strings.Map(func(r rune) rune {
return r + 32
}, "ABCDEFGHIJK"))
fmt.Println(strings.Map(func(r rune) rune {
if r < 'F' {
return -1
} else {
return r
}
}, "ABCDEFGHIJK"))
}الإخراج
=== RUN TestMap
ABCDEFGHIJK
abcdefghijk
FGHIJK
--- PASS: TestMap (0.00s)
PASSتكرار نسخ السلسلة
نسخ السلسلة حسب العدد المحدد، إذا كان سالباً سيسبب panic
func Repeat(s string, count int) stringمثال
func TestRepeat(t *testing.T) {
fmt.Println(strings.Repeat("a", 10))
fmt.Println(strings.Repeat("abc", 10))
}الإخراج
=== RUN TestRepeat
aaaaaaaaaa
abcabcabcabcabcabcabcabcabcabc
--- PASS: TestRepeat (0.00s)
PASSاستبدال السلسلة
s هي السلسلة الأصلية، وold هو الجزء المراد استبداله، وnew هو جزء الاستبدال لـ old، وn هو عدد مرات الاستبدال، عندما n أقل من 0 يعني عدم تقييد عدد مرات الاستبدال.
func Replace(s, old, new string, n int) stringمثال
func TestReplace(t *testing.T) {
fmt.Println(strings.Replace("Hello this is golang", "golang", "c++", 1))
fmt.Println(strings.Replace("Hello this is golang", "o", "c", -1))
fmt.Println(strings.Replace("Hello this is golang", "o", "c", 1))
}الإخراج
=== RUN TestReplace
Hello this is c++
Hellc this is gclang
Hellc this is golang
--- PASS: TestReplace (0.00s)
PASSدالة ملائمة لـ Replace، تكافئ stings.Replace(s,old,new,-1)
func ReplaceAll(s, old, new string) stringمثال
func TestReplaceAll(t *testing.T) {
fmt.Println(strings.ReplaceAll("Hello this is golang", "o", "c++"))
}الإخراج
=== RUN TestReplaceAll
Hellc++ this is gc++lang
--- PASS: TestReplaceAll (0.00s)
PASSفصل السلسلة
فصل السلسلة s إلى شريحة سلاسل حسب السلسلة الفرعية sep
func Split(s, sep string) []stringفصل السلسلة s إلى شريحة سلاسل حسب السلسلة الفرعية sep، وعدد مرات الفصل يحدده n
func SplitN(s, sep string, n int) []stringفصل السلسلة s إلى شريحة سلاسل تتضمن عناصر تحتوي على sep
func SplitAfter(s, sep string) []stringفصل السلسلة s إلى شريحة سلاسل تتضمن عناصر تحتوي على sep، وعدد مرات الفصل يحدده n
func SplitAfterN(s, sep string, n int) []stringمثال
func TestSplit(t *testing.T) {
fmt.Printf("%q\n", strings.Split("this is go language", " "))
fmt.Printf("%q\n", strings.SplitN("this is go language", " ", 2))
fmt.Printf("%q\n", strings.SplitAfter("this is go language", " "))
fmt.Printf("%q\n", strings.SplitAfterN("this is go language", " ", 2))
}الإخراج
=== RUN TestSplit
["this" "is" "go" "language"]
["this" "is go language"]
["this " "is " "go " "language"]
["this " "is go language"]
--- PASS: TestSplit (0.00s)
PASSتحويل حالة الأحرف
تحويل السلسلة الإنجليزية إلى أحرف صغيرة
func ToLower(s string) stringالتحويل إلى أحرف صغيرة حسب اللغة المحددة عبر unicode.SpecialCase
func ToLowerSpecial(c unicode.SpecialCase, s string) stringتحويل السلسلة الإنجليزية إلى أحرف كبيرة
func ToUpper(s string) stringالتحويل إلى أحرف كبيرة حسب اللغة المحددة عبر unicode.SpecialCase
func ToUpperSpecial(c unicode.SpecialCase, s string) stringمثال
func TestLowerAndUpper(t *testing.T) {
fmt.Println(strings.ToLower("My name is jack,Nice to meet you!"))
fmt.Println(strings.ToLowerSpecial(unicode.TurkishCase, "Önnek İş"))
fmt.Println(strings.ToUpper("My name is jack,Nice to meet you!"))
fmt.Println(strings.ToUpperSpecial(unicode.TurkishCase, "örnek iş"))
}الإخراج
=== RUN TestLowerAndUpper
my name is jack,nice to meet you!
önnek iş
MY NAME IS JACK,NICE TO MEET YOU!
ÖRNEK İŞ
--- PASS: TestLowerAndUpper (0.00s)
PASSتقليم السلسلة
تقليم طرفي السلسلة، وحذف أي سلسلة فرعية تطابق cutset
func Trim(s, cutset string) stringتقليم الطرف الأيسر للسلسلة، وحذف أي سلسلة فرعية تطابق cutset
func TrimLeft(s, cutset string) stringتقليم بادئة الطرف الأيسر للسلسلة، وحذف السلسلة الفرعية التي تطابق cutset، إذا لم تتطابق تُرجع السلسلة s
func TrimPrefix(s, suffix string) stringتقليم الطرف الأيمن للسلسلة، وحذف أي سلسلة فرعية تطابق cutset
func TrimRight(s, cutset string) stringتقليم لاحقة الطرف الأيمن للسلسلة، وحذف السلسلة الفرعية التي تطابق cutset، إذا لم تتطابق تُرجع السلسلة s
func TrimSuffix(s, suffix string) stringمثال
func TestTrim(t *testing.T) {
fmt.Println(strings.Trim("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimLeft("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimRight("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimPrefix("!!this is a test statement!!", "!!!"))
fmt.Println(strings.TrimSuffix("!!this is a test statement!!", "!!!"))
}الإخراج
=== RUN TestTrim
this is a test statement
this is a test statement!!
!!this is a test statement
!!this is a test statement!!
!!this is a test statement!!
--- PASS: TestTrim (0.00s)
PASSمنشئ السلاسل Builder
منشئ السلاسل Builder أكثر توفيراً للذاكرة من التعامل المباشر مع السلاسل.
type Builder struct {
// حقول داخلية غير مكشوفة للخارج
}مثال
func TestBuilder(t *testing.T) {
builder := strings.Builder{}
builder.WriteString("hello")
builder.WriteString(" world")
fmt.Println(builder.Len())
fmt.Println(builder.String())
}الإخراج
=== RUN TestBuilder
11
hello world
--- PASS: TestBuilder (0.00s)
PASSTIP
لا تحاول تمرير Builder كقيمة، مثلاً عند تمرير strings.Builder كمعامل دالة، سيُسبب البرنامج panic
strings: illegal use of non-zero Builder copied by valueيوجد داخلياً الكود التالي
type Builder struct {
addr *Builder // عنوانه الخاص
buf []byte
}
func (b *Builder) copyCheck() {
if b.addr == nil {
b.addr = (*Builder)(noescape(unsafe.Pointer(b)))
} else if b.addr != b {
panic("strings: illegal use of non-zero Builder copied by value")
}
}عند نسخ Builder كقيمة، يتم أيضاً نسخ مؤشر الشريحة الداخلية، وكلا Builder عند كتابة السلاسل يتعاملان مع نفس الشريحة، وهذا هو السبب في عدم السماح بالنسخ كقيمة.
مستبدل السلاسل Replacer
Replacer مخصص لاستبدال السلاسل
func NewReplacer(oldnew ...string) *Replacerمثال
func TestReplacer(t *testing.T) {
r := strings.NewReplacer("<", "<", ">", ">")
fmt.Println(r.Replace("This is <b>HTML</b>!"))
}الإخراج
This is <b>HTML</b>!قارئ السلاسل Reader
ينفذ Reader الواجهات io.Reader, io.ReaderAt, io.ByteReader, io.ByteScanner, io.RuneReader, io.RuneScanner, io.Seeker, و io.WriterTo interfaces.
func NewReader(s string) *Readerمثال
func TestReader(t *testing.T) {
reader := strings.NewReader("abcdefghijk")
buffer := make([]byte, 20, 20)
read, err := reader.Read(buffer)
if err != nil {
log.Panic(err)
}
fmt.Println(read)
fmt.Println(string(buffer))
}الإخراج
=== RUN TestReader
11
abcdefghijk
--- PASS: TestReader (0.00s)
PASS