जवाबों:
दोनों शैलियों का उपयोग गो के मानक पुस्तकालयों के भीतर किया जाता है।
if len(s) > 0 { ... }
strconv
पैकेज में पाया जा सकता है : http://golang.org/src/pkg/strconv/atoi.go
if s != "" { ... }
encoding/json
पैकेज में पाया जा सकता है : http://golang.org/src/pkg/encoding/json/encode.go
दोनों मुहावरेदार हैं और पर्याप्त स्पष्ट हैं। यह व्यक्तिगत स्वाद और स्पष्टता के बारे में अधिक बात है।
रस कॉक्स एक गोल-नट धागा में लिखते हैं :
वह जो कोड को स्पष्ट करता है।
अगर मैं तत्व x को देखने वाला हूं, तो मैं आमतौर पर
len (s)> x, यहां तक कि x == 0 के लिए भी लिखता हूं , लेकिन अगर मुझे
"इस बात की परवाह है " तो यह विशिष्ट स्ट्रिंग है "मैं s ==" लिखना चाहता हूं।यह मानना उचित है कि एक परिपक्व संकलक
len (s) == 0 और s == "" को एक ही, कुशल कोड में संकलित करेगा ।
...कोड स्पष्ट करें।
जैसा कि टिम्मम के जवाब में कहा गया है , गो संकलक दोनों मामलों में समान कोड उत्पन्न करता है।
len(v) > 0
में h2_bundle.go (लाइन 2702)। यह स्वचालित रूप से नहीं दिखाया गया है क्योंकि यह golang.org/x/net/http2 से उत्पन्न होता है, मेरा मानना है।
यह समय से पहले microoptimization लगता है। संकलक दोनों मामलों के लिए या कम से कम इन दोनों के लिए समान कोड का उत्पादन करने के लिए स्वतंत्र है
if len(s) != 0 { ... }
तथा
if s != "" { ... }
क्योंकि शब्दार्थ स्पष्ट रूप से समान है।
लंबाई की जाँच करना एक अच्छा जवाब है, लेकिन आप "खाली" स्ट्रिंग के लिए भी जिम्मेदार हो सकते हैं, जो कि केवल व्हाट्सएप भी है। "तकनीकी रूप से" खाली नहीं है, लेकिन अगर आप जांचना चाहते हैं:
package main
import (
"fmt"
"strings"
)
func main() {
stringOne := "merpflakes"
stringTwo := " "
stringThree := ""
if len(strings.TrimSpace(stringOne)) == 0 {
fmt.Println("String is empty!")
}
if len(strings.TrimSpace(stringTwo)) == 0 {
fmt.Println("String two is empty!")
}
if len(stringTwo) == 0 {
fmt.Println("String two is still empty!")
}
if len(strings.TrimSpace(stringThree)) == 0 {
fmt.Println("String three is empty!")
}
}
TrimSpace
मूल स्ट्रिंग से एक नई स्ट्रिंग को आवंटित और कॉपी करेगा, इसलिए यह दृष्टिकोण पैमाने पर अक्षमता का परिचय देगा।
s
प्रकार स्ट्रिंग का है, s[0:i]
एक नई प्रति लौटाता है। स्ट्रिंग्स गो में अपरिवर्तनीय हैं, इसलिए क्या यहां एक प्रति बनाने की आवश्यकता है?
strings.TrimSpace( s )
यदि स्ट्रिंग को ट्रिमिंग की आवश्यकता नहीं है, तो नए स्ट्रिंग आवंटन और वर्ण प्रतिलिपि का कारण नहीं होगा, लेकिन यदि स्ट्रिंग को ट्रिमिंग की आवश्यकता है, तो अतिरिक्त प्रतिलिपि (बिना व्हाट्सएप वर्ण) को आमंत्रित किया जाएगा।
gocritic
लिंटर उपयोग करने का सुझाव strings.TrimSpace(str) == ""
लंबाई जांच के बजाय।
यह मानते हुए कि खाली स्थान और सभी प्रमुख और पीछे वाले सफेद स्थानों को हटा दिया जाना चाहिए:
import "strings"
if len(strings.TrimSpace(s)) == 0 { ... }
इसलिये :
len("") // is 0
len(" ") // one empty space is 1
len(" ") // two empty spaces is 2
< 1
1 है
अब तक, गो संकलक दोनों मामलों में समान कोड बनाता है, इसलिए यह स्वाद का मामला है। GCCGo अलग कोड उत्पन्न करता है, लेकिन बमुश्किल कोई भी इसका उपयोग करता है इसलिए मुझे इस बारे में चिंता नहीं होगी।
नीचे दिए गए फ़ंक्शन की तरह उपयोग करने के लिए यह क्लीनर और कम त्रुटि वाला होगा:
func empty(s string) bool {
return len(strings.TrimSpace(s)) == 0
}
बस टिप्पणी में और जोड़ने के लिए
मुख्य रूप से प्रदर्शन परीक्षण कैसे करें।
मैंने निम्नलिखित कोड के साथ परीक्षण किया:
import (
"testing"
)
var ss = []string{"Hello", "", "bar", " ", "baz", "ewrqlosakdjhf12934c r39yfashk fjkashkfashds fsdakjh-", "", "123"}
func BenchmarkStringCheckEq(b *testing.B) {
c := 0
b.ResetTimer()
for n := 0; n < b.N; n++ {
for _, s := range ss {
if s == "" {
c++
}
}
}
t := 2 * b.N
if c != t {
b.Fatalf("did not catch empty strings: %d != %d", c, t)
}
}
func BenchmarkStringCheckLen(b *testing.B) {
c := 0
b.ResetTimer()
for n := 0; n < b.N; n++ {
for _, s := range ss {
if len(s) == 0 {
c++
}
}
}
t := 2 * b.N
if c != t {
b.Fatalf("did not catch empty strings: %d != %d", c, t)
}
}
func BenchmarkStringCheckLenGt(b *testing.B) {
c := 0
b.ResetTimer()
for n := 0; n < b.N; n++ {
for _, s := range ss {
if len(s) > 0 {
c++
}
}
}
t := 6 * b.N
if c != t {
b.Fatalf("did not catch empty strings: %d != %d", c, t)
}
}
func BenchmarkStringCheckNe(b *testing.B) {
c := 0
b.ResetTimer()
for n := 0; n < b.N; n++ {
for _, s := range ss {
if s != "" {
c++
}
}
}
t := 6 * b.N
if c != t {
b.Fatalf("did not catch empty strings: %d != %d", c, t)
}
}
और परिणाम थे:
% for a in $(seq 50);do go test -run=^$ -bench=. --benchtime=1s ./...|grep Bench;done | tee -a log
% sort -k 3n log | head -10
BenchmarkStringCheckEq-4 150149937 8.06 ns/op
BenchmarkStringCheckLenGt-4 147926752 8.06 ns/op
BenchmarkStringCheckLenGt-4 148045771 8.06 ns/op
BenchmarkStringCheckNe-4 145506912 8.06 ns/op
BenchmarkStringCheckLen-4 145942450 8.07 ns/op
BenchmarkStringCheckEq-4 146990384 8.08 ns/op
BenchmarkStringCheckLenGt-4 149351529 8.08 ns/op
BenchmarkStringCheckNe-4 148212032 8.08 ns/op
BenchmarkStringCheckEq-4 145122193 8.09 ns/op
BenchmarkStringCheckEq-4 146277885 8.09 ns/op
प्रभावी रूप से वेरिएंट आमतौर पर सबसे तेज समय तक नहीं पहुंचता है और वेरिएंट टॉप स्पीड के बीच केवल न्यूनतम अंतर (लगभग 0.01ns / op) होता है।
और अगर मैं पूर्ण लॉग देखता हूं, तो कोशिशों के बीच का अंतर बेंचमार्क कार्यों के बीच अंतर से अधिक है।
इसके अलावा BenchmarkStringCheckEq और BenchmarkStringCheckNe या BenchmarkStringCheckLen और BenchmarkStringCheckLenGt के बीच कोई भी औसत दर्जे का अंतर नहीं लगता है, जबकि बाद वाले वेरिएंट को भी 2 बार के बजाय 6 गुना इंक चाहिए।
आप संशोधित परीक्षण या इनर लूप के साथ परीक्षणों को जोड़कर समान प्रदर्शन के बारे में कुछ आत्मविश्वास प्राप्त करने की कोशिश कर सकते हैं। यह तेज़ है:
func BenchmarkStringCheckNone4(b *testing.B) {
c := 0
b.ResetTimer()
for n := 0; n < b.N; n++ {
for _, _ = range ss {
c++
}
}
t := len(ss) * b.N
if c != t {
b.Fatalf("did not catch empty strings: %d != %d", c, t)
}
}
यह तेज नहीं है:
func BenchmarkStringCheckEq3(b *testing.B) {
ss2 := make([]string, len(ss))
prefix := "a"
for i, _ := range ss {
ss2[i] = prefix + ss[i]
}
c := 0
b.ResetTimer()
for n := 0; n < b.N; n++ {
for _, s := range ss2 {
if s == prefix {
c++
}
}
}
t := 2 * b.N
if c != t {
b.Fatalf("did not catch empty strings: %d != %d", c, t)
}
}
दोनों वेरिएंट मुख्य परीक्षणों के बीच अंतर की तुलना में आमतौर पर तेज़ या धीमे होते हैं।
प्रासंगिक वितरण के साथ स्ट्रिंग जनरेटर का उपयोग करके परीक्षण स्ट्रिंग्स (ss) उत्पन्न करना भी अच्छा होगा। और चर लंबाई भी है।
इसलिए मुझे मुख्य विधियों के बीच प्रदर्शन के अंतर का कोई भरोसा नहीं है, ताकि खाली स्ट्रिंग का परीक्षण किया जा सके।
और मैं कुछ आत्मविश्वास के साथ कह सकता हूं, यह तेजी से है कि खाली स्ट्रिंग को टेस्ट न करें। और यह भी 1 चर स्ट्रिंग (उपसर्ग संस्करण) का परीक्षण करने की तुलना में खाली स्ट्रिंग का परीक्षण करने के लिए तेज़ है।
आधिकारिक दिशानिर्देशों के अनुसार और प्रदर्शन के दृष्टिकोण से वे समतुल्य दिखाई देते हैं ( एनीसस उत्तर ), एस! = "" एक वाक्यविन्यास लाभ के कारण बेहतर होगा। s! = "" संकलन समय पर विफल हो जाएगा यदि चर एक स्ट्रिंग नहीं है, जबकि len (s) == 0 कई अन्य डेटा प्रकारों के लिए पारित होगा।
len()
बस उस छोटे से अतिरिक्त काम की आवश्यकता है। फिर भी, एक चीज़ जो हम C में करते थे, वह बाईं ओर डाली गई थी const
या ऑपरेटर के बाईं ओर स्थिर स्ट्रिंग को रखने के लिए s == "" को s = "" बनने से रोकने के लिए थी, जो C वाक्यविन्यास में स्वीकार्य है। .. और शायद गोलंग भी। (अगर विस्तारित देखें)
यह पूरे स्ट्रिंग को ट्रिम करने की तुलना में अधिक प्रदर्शनकारी होगा, क्योंकि आपको केवल कम से कम एक सिंगल-स्पेस चरित्र की जांच करने की आवश्यकता है
// Strempty checks whether string contains only whitespace or not
func Strempty(s string) bool {
if len(s) == 0 {
return true
}
r := []rune(s)
l := len(r)
for l > 0 {
l--
if !unicode.IsSpace(r[l]) {
return false
}
}
return true
}
मुझे लगता है कि खाली स्ट्रिंग के साथ तुलना करने का सबसे अच्छा तरीका है
BenchmarkStringCheck1 रिक्त स्ट्रिंग के साथ जाँच कर रहा है
BenchmarkStringCheck2 लेन ज़ेन के साथ जाँच कर रहा है
मैं खाली और गैर-रिक्त स्ट्रिंग जाँच के साथ जाँच करता हूँ। आप देख सकते हैं कि रिक्त स्ट्रिंग के साथ जाँच तेज है।
BenchmarkStringCheck1-4 2000000000 0.29 ns/op 0 B/op 0 allocs/op
BenchmarkStringCheck1-4 2000000000 0.30 ns/op 0 B/op 0 allocs/op
BenchmarkStringCheck2-4 2000000000 0.30 ns/op 0 B/op 0 allocs/op
BenchmarkStringCheck2-4 2000000000 0.31 ns/op 0 B/op 0 allocs/op
कोड
func BenchmarkStringCheck1(b *testing.B) {
s := "Hello"
b.ResetTimer()
for n := 0; n < b.N; n++ {
if s == "" {
}
}
}
func BenchmarkStringCheck2(b *testing.B) {
s := "Hello"
b.ResetTimer()
for n := 0; n < b.N; n++ {
if len(s) == 0 {
}
}
}
if mystring != "" { }
सबसे अच्छा, पसंदीदा और मुहावरेदार तरीका TODAY है। कारण मानक पुस्तकालय में अन्यथा शामिल है क्योंकि यह 2010 से पहले लिखा गया था जबlen(mystring) == 0
अनुकूलन ने समझदारी की।