2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
सामग्रीसूची
2. Go भाषायां मूल्यान्तरणस्य तथा पतास्थापनस्य (सन्दर्भस्थापनस्य) उपयोगः कथं करणीयः? किं भेदः ?
4.गो कन्वे इति किम् ? सामान्यतः किं प्रयुज्यते ?
5.विलम्बस्य कार्याणि लक्षणानि च कानि सन्ति ?
6.Go slice इत्यस्य अन्तर्निहितं कार्यान्वयनम्? स्लाइस् विस्तारतन्त्रं गच्छतु?
7. विस्तारात् पूर्वं पश्चात् च स्लाइस् समानाः सन्ति वा ?
8.स्लाइस् किमर्थं सूत्र-सुरक्षितः नास्ति ?
भेदाः : 1. Make इत्यस्य उपयोगः केवलं slice, map, chan इति प्रकारस्य आँकडानां आवंटनार्थं, आरम्भार्थं च कर्तुं शक्यते यदा new इत्यनेन कस्यापि प्रकारस्य आँकडानां आवंटनं कर्तुं शक्यते;
2. नूतनं आवंटनं एकं सूचकं प्रत्यागच्छति, यत् "*Type" इति प्रकारः अस्ति, यदा make एकं सन्दर्भं प्रत्यागच्छति, यत् Type अस्ति;
3. new द्वारा आवंटितं स्थानं स्वच्छं भविष्यति make इत्यनेन स्थानं आवंटितस्य अनन्तरं, तत् आरभ्यते।
मूल्यं पारयित्वा केवलं पैरामीटर् इत्यस्य मूल्यं प्रतिलिख्य तत्सम्बद्धे फंक्शन् मध्ये स्थापयति चरद्वयस्य पता भिन्नाः सन्ति, परस्परं परिवर्तयितुं न शक्नुवन्ति ।
Address passing (passing by reference) इत्यनेन चरं स्वयं तत्सम्बद्धे फंक्शन् मध्ये पारितं भविष्यति, तथा च चरस्य मूल्यसामग्री फंक्शन् मध्ये परिवर्तयितुं शक्यते ।
सरणीः : १.
सरणी नियतदीर्घता सरणीयाः दीर्घता सरणीप्रकारस्य भागः अस्ति, अतः [3]int तथा [4]int द्वौ भिन्नौ सरणीप्रकारौ स्तः यदि न निर्दिष्टः तर्हि आकारः स्वयमेव गण्यते initialization pair.एरे परिवर्तनं कर्तुं न शक्यते
अंश:
स्लाइस् इत्यस्य दीर्घता परिवर्तयितुं शक्यते । स्लाइस् पताद्वारा (सन्दर्भद्वारा पारितः भवति) तथा च सरणीद्वारा अथवा बिल्ट-इन् फंक्शन् make() इत्यस्य माध्यमेन आरम्भः कर्तुं शक्यते आरम्भीकरणस्य समये ततः len=cap विस्तारितः भवति ।
सरणीः मूल्यप्रकाराः स्लाइस् च सन्दर्भप्रकाराः सन्ति;
सरणीनां दीर्घता नियतं भवति, परन्तु स्लाइस् न (स्लाइस् गतिशीलसरणयः सन्ति) ।
स्लाइस् इत्यस्य अन्तर्निहितः स्तरः एकः सरणी अस्ति
Go भाषायाः स्लाइस् विस्तारतन्त्रम् अतीव चतुरं भवति यत् अन्तर्निहितं सरणीं पुनः आवंटयित्वा नूतनसरण्यां दत्तांशं प्रवासयित्वा विस्तारं प्राप्नोति । विशेषतः यदा स्लाइस् विस्तारस्य आवश्यकता भवति तदा Go भाषा नूतनं अन्तर्निहितं सरणीं निर्माय मूलसरणौ विद्यमानं दत्तांशं नूतनसरणौ प्रतिलिखति । ततः, स्लाइस् सूचकः नूतनं सरणीं प्रति सूचयति, दीर्घता मूलदीर्घतायाः प्लस् विस्तारितदीर्घतायाः कृते अद्यतनं भवति, क्षमता च नूतनसरण्याः दीर्घतायां अद्यतनं भवति
स्लाइस् विस्तारं प्राप्तुं : १.
गच्छ1.17
- // src/runtime/slice.go
-
- func growslice(et *_type, old slice, cap int) slice {
- // ...
-
- newcap := old.cap
- doublecap := newcap + newcap
- if cap > doublecap {
- newcap = cap
- } else {
- if old.cap < 1024 {
- newcap = doublecap
- } else {
- // Check 0 < newcap to detect overflow
- // and prevent an infinite loop.
- for 0 < newcap && newcap < cap {
- newcap += newcap / 4
- }
- // Set newcap to the requested cap when
- // the newcap calculation overflowed.
- if newcap <= 0 {
- newcap = cap
- }
- }
- }
-
- // ...
-
- return slice{p, old.len, newcap}
- }
स्मृतिस्थानं आवंटयितुं पूर्वं, भवद्भिः नूतनं स्लाइस् क्षमता निर्धारयितुं आवश्यकं भवति रनटाइम् इत्यत्र, भवन्तः स्लाइस् इत्यस्य वर्तमानक्षमतायाः आधारेण विस्तारार्थं भिन्नाः रणनीतयः चयनं कर्तुं शक्नुवन्ति:
यदि अपेक्षितक्षमता वर्तमानक्षमतायाः द्विगुणाधिका भवति तर्हि अपेक्षितक्षमतायाः उपयोगः भविष्यति यदि वर्तमानस्य स्लाइस् इत्यस्य दीर्घता १०२४ तः न्यूना भवति तर्हि क्षमता दुगुणा भविष्यति यदि वर्तमानस्य स्लाइस् इत्यस्य दीर्घता तस्मात् अधिका वा समाना भवति १०२४, क्षमता प्रतिवारं २५% वर्धिता भविष्यति यावत् नूतनक्षमता अपेक्षितापेक्षया अधिका क्षमता;
गच्छ1.18
- // src/runtime/slice.go
-
- func growslice(et *_type, old slice, cap int) slice {
- // ...
-
- newcap := old.cap
- doublecap := newcap + newcap
- if cap > doublecap {
- newcap = cap
- } else {
- const threshold = 256
- if old.cap < threshold {
- newcap = doublecap
- } else {
- // Check 0 < newcap to detect overflow
- // and prevent an infinite loop.
- for 0 < newcap && newcap < cap {
- // 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) / 4
- }
- // Set newcap to the requested cap when
- // the newcap calculation overflowed.
- if newcap <= 0 {
- newcap = cap
- }
- }
- }
-
- // ...
-
- return slice{p, old.len, newcap}
- }
-
पूर्वसंस्करणात् भेदः मुख्यतया विस्तारदहलीजस्य अस्याः कोडपङ्क्तौ च अस्ति:newcap += (newcap + 3*threshold) / 4
。
स्मृतिस्थानं आवंटयितुं पूर्वं, भवद्भिः नूतनं स्लाइस् क्षमता निर्धारयितुं आवश्यकं भवति रनटाइम् इत्यत्र, भवन्तः स्लाइस् इत्यस्य वर्तमानक्षमतायाः आधारेण विस्तारार्थं भिन्नाः रणनीतयः चयनं कर्तुं शक्नुवन्ति:
यदि अपेक्षितक्षमता वर्तमानक्षमतायाः द्विगुणाधिका भवति तर्हि अपेक्षितक्षमता उपयुज्यते;
यदि वर्तमानस्लाइस् इत्यस्य दीर्घता दहलीजात् न्यूना भवति (पूर्वनिर्धारितं २५६), तर्हि क्षमता दुगुणा भविष्यति;
यदि वर्तमानस्य स्लाइस् इत्यस्य दीर्घता दहलीजात् अधिका वा समाना वा भवति (पूर्वनिर्धारित 256), तर्हि प्रत्येकं समये क्षमता 25% वर्धिता भविष्यति The benchmark is newcap + 3*threshold
, यावत् नूतनक्षमता अपेक्षितक्षमतायाः अपेक्षया अधिका न भवति;
स्लाइस् विस्तारः द्वयोः चरणयोः विभक्तः भवति, गोतः पूर्वं पश्चात् च1.18:
1. गमनात् पूर्वं1.18:
यदि अपेक्षितक्षमता वर्तमानक्षमतायाः द्विगुणाधिका भवति तर्हि अपेक्षितक्षमता उपयुज्यते;
यदि वर्तमानस्य स्लाइस् इत्यस्य दीर्घता १०२४ तः न्यूना भवति तर्हि क्षमता द्विगुणा भविष्यति;
यदि वर्तमानस्य स्लाइस् इत्यस्य दीर्घता १०२४ तः अधिका भवति तर्हि प्रत्येकं समये क्षमता २५% वर्धिता भविष्यति यावत् नूतना क्षमता अपेक्षितक्षमतायाः अपेक्षया अधिका न भवति
2. गमनानन्तरं1.18:
यदि अपेक्षितक्षमता वर्तमानक्षमतायाः द्विगुणाधिका भवति तर्हि अपेक्षितक्षमता उपयुज्यते;
यदि वर्तमानस्लाइस् इत्यस्य दीर्घता दहलीजात् न्यूना भवति (पूर्वनिर्धारितं २५६), तर्हि क्षमता दुगुणा भविष्यति;
यदि वर्तमानस्य स्लाइस् इत्यस्य दीर्घता दहलीजात् अधिका वा समाना वा भवति (पूर्वनिर्धारित 256), तर्हि प्रत्येकं समये क्षमता 25% वर्धिता भविष्यति The benchmark is newcap + 3*threshold
, यावत् नूतनक्षमता अपेक्षितक्षमतायाः अपेक्षया अधिका न भवति;
go convey इति एककपरीक्षणरूपरेखा अस्ति यत् golang इत्यस्य समर्थनं करोति
go convey स्वयमेव सञ्चिकासंशोधनं निरीक्षितुं परीक्षणं च आरभुं शक्नोति, तथा च वास्तविकसमये जालान्तरफलके परीक्षणपरिणामान् निर्गन्तुं शक्नोति
go convey परीक्षाप्रकरणानाम् लेखनं सरलीकर्तुं समृद्धानि प्रतिपादनानि प्रदाति
स्थगितस्य कार्यम् अस्ति : १.
defer कृते आवश्यकं वाक्यविन्यासं पूर्णं कर्तुं सामान्यं फंक्शन् अथवा मेथड् आह्वयितुं पूर्वं भवद्भिः केवलं defer इति कीवर्डं योजयितुं आवश्यकम् । यदा defer स्टेट्मेण्ट् निष्पादितं भवति तदा defer इत्यस्य अनन्तरं कार्यं स्थगितम् भविष्यति । defer इत्यस्य अनन्तरं कार्यं यावत् defer स्टेट्मेण्ट् युक्तं फंक्शन् निष्पादितं तावत् न निष्पादितं भविष्यति, यद्यपि defer स्टेट्मेण्ट् युक्तं फंक्शन् सामान्यरूपेण return मार्गेण समाप्तं भवति वा आतङ्कस्य कारणेन असामान्यतया समाप्तं भवति वा इति न कृत्वा भवन्तः एकस्मिन् फंक्शन् मध्ये बहुविधं defer स्टेट्मेण्ट् निष्पादयितुं शक्नुवन्ति, तेषां घोषणायाः विपरीतक्रमेण ।
स्थगनार्थं सामान्यपरिदृश्यानि : १.
defer स्टेट्मेण्ट् प्रायः युग्मितक्रियाणां निबन्धनार्थं भवति, यथा तालानां उद्घाटनं, बन्दीकरणं, संयोजनं, विच्छेदनं, ताडनं, मुक्तिः च ।
defer mechanism इत्यस्य माध्यमेन, function logic कियत् अपि जटिलं न भवतु, संसाधनं कस्मिन् अपि निष्पादनमार्गे मुक्तस्य गारण्टीं दातुं शक्यते ।
स्लाइसिंग् इत्येतत् सरणीम् आधारीकृत्य कार्यान्वितं भवति तस्य अन्तर्निहितः स्तरः स्वयं अतीव लघुः अस्ति तथा च अन्तर्निहितस्य सरणीयाः अमूर्तरूपेण अवगन्तुं शक्यते । यतः एतत् सरणीनां आधारेण कार्यान्वितं भवति, तस्य अन्तर्निहितस्मृतिः निरन्तरं आवंटिता भवति, यत् अतीव कार्यक्षमम् अस्ति, अनुक्रमणिकाद्वारा अपि Data प्राप्तुं शक्यते, तथा च एतत् पुनरावृत्तिः, कचरासंग्रहणं च अनुकूलितं कर्तुं शक्यते स्लाइस् स्वयं गतिशीलाः सरणीः अथवा सरणीसूचकाः न सन्ति । आन्तरिकरूपेण कार्यान्विता दत्तांशसंरचना सूचकस्य माध्यमेन अन्तर्निहितं सरणीं निर्दिशति, तथा च प्रासंगिकगुणाः दत्तांशपठनलेखनक्रियाः निर्दिष्टक्षेत्रे सीमितुं सेट् भवन्ति स्लाइस् स्वयं केवलं पठनीयं वस्तु अस्ति, तस्य कार्यतन्त्रं च एरे सूचकस्य एन्कैप्सुलेशनस्य सदृशं भवति ।
स्लाइस् ऑब्जेक्ट् अतीव लघु अस्ति यतः एतत् केवलं ३ क्षेत्राणि युक्तं दत्तांशसंरचना अस्ति:
अन्तर्निहित सरणीं प्रति सूचकः
स्लाइस् लम्बता
स्लाइस् क्षमता
गो (१.१७) इत्यस्मिन् विस्तारस्य स्लाइसिंग् इत्यस्य रणनीतिः निम्नलिखितरूपेण अस्ति ।
प्रथमः न्यायाधीशः, यदि नवप्रयुक्ता क्षमता पुरातनक्षमतायाः २ गुणाधिका भवति तर्हि अन्तिमक्षमता नवप्रयुक्ता क्षमता भविष्यति।
अन्यथा यदि पुरातनस्य स्लाइस् इत्यस्य दीर्घता १०२४ इत्यस्मात् न्यूना भवति तर्हि अन्तिमक्षमता पुरातनक्षमतायाः द्विगुणा भविष्यति ।
अन्यथा यदि पुरातनं स्लाइस् दीर्घता १०२४ इत्यस्मात् अधिका वा समं वा भवति तर्हि अन्तिमक्षमता पुरातनक्षमतायाः १/४ चक्रीयरूपेण वर्धिता भविष्यति यावत् अन्तिमक्षमता नवानुरोधितक्षमतायाः अधिका वा समाना वा न भवति
यदि अन्तिमक्षमतागणनामूल्यं अतिप्रवाहितं भवति तर्हि अन्तिमक्षमता नवानुरोधितक्षमता भवति ।
स्थितिः प्रथमः : १.
मूलसरणौ अद्यापि विस्तारयितुं शक्यते (वास्तविकक्षमता न पूरिता अस्ति) अस्मिन् सन्दर्भे विस्तारिता सरणी अद्यापि मूलसरणौ सूचयति अंश।
स्थितिः द्वितीयः : १.
एतत् निष्पद्यते यत् सरणीयाः क्षमता अधिकतमं मूल्यं प्राप्तवती अस्ति यदि भवान् क्षमतां विस्तारयितुम् इच्छति तर्हि Go प्रथमं पूर्वनिर्धारितरूपेण स्मृतिक्षेत्रं उद्घाटयिष्यति, मूलमूल्यं प्रतिलिखति, ततः append() कार्यं करिष्यति एषा स्थितिः मूलसरणीं सर्वथा न प्रभावितं करोति । Slice इत्यस्य प्रतिलिपिं कर्तुं Copy फंक्शन् इत्यस्य उपयोगः सर्वोत्तमः ।
slice底层结构并没有使用加锁等方式,不支持并发读写,所以并不是线程安全的, 使用多个 goroutine 对类型为 slice 的变量进行操作,每次输出的值大概率都不会一样,与预期值不一致; slice在并发执行中不会报错,但是数据会丢失 如果想实现slice线程安全,有两种方式: 方式一:通过加锁实现slice线程安全,适合对性能要求不高的场景。
- func TestSliceConcurrencySafeByMutex(t *testing.T) {
- var lock sync.Mutex //互斥锁
- a := make([]int, 0)
- var wg sync.WaitGroup
- for i := 0; i < 10000; i++ {
- wg.Add(1)
- go func(i int) {
- defer wg.Done()
- lock.Lock()
- defer lock.Unlock()
- a = append(a, i)
- }(i)
- }
- wg.Wait()
- t.Log(len(a))
- // equal 10000
- }
-
方式二:通过channel实现slice线程安全,适合对性能要求高的场景。
- func TestSliceConcurrencySafeByChanel(t *testing.T) {
- buffer := make(chan int)
- a := make([]int, 0)
- // 消费者
- go func() {
- for v := range buffer {
- a = append(a, v)
- }
- }()
- // 生产者
- var wg sync.WaitGroup
- for i := 0; i < 10000; i++ {
- wg.Add(1)
- go func(i int) {
- defer wg.Done()
- buffer <- i
- }(i)
- }
- wg.Wait()
- t.Log(len(a))
- // equal 10000
- }