æç« ç®å½
-
-
-
- åè¨
- åä¸é´è
- å¤ä¸é´è
-
- æµç¨å¾
- æµç¨å¾åæ
- æµç¨å¾æ»ç»
- æµæ°´çº¿ç¤ºæå¾
- æ´ä½æ»ç»
- ä¹åçé®é¢æ¯å¦å·²ç»è¿åè解
- æ´å¤é 读
-
-
ç¸å ³æç« ï¼
- [ç¿»è¯]Go并å模å¼ï¼æ建åç»æ¢æµæ°´çº¿
- go pipelineçæµæ°´çº¿ç¤ºæå¾
- chanåºæ¬ç¥è¯
- goä¸å ³äºfor循ç¯çç¥è¯
- å¤è¿ç¨éä¿¡
åè¨
å¦ä¹ goè¯è¨å·²ç»æå 个æï¼ä½æ¯å ³äºgoä¸çç¹æ§chanåroutineçåºç¨è¿ä¸æ¯å¾ç解ï¼å¦ææä¸æchanåroutineçæºå¶å°±å¾é¾æµç çç¨goç¼ååºå¥å£®çç¨åºãæ以æè§å¾å ³äºchanåºç¨çç¼ç¨ï¼æ¯å¯ä»¥è®²ä¸è®²çã
é£æ们é¦å ä¼æ³å°å 个é®é¢ï¼
- 使ç¨chanç代ç ä¸æ®éç代ç æä»ä¹ä¸ååï¼
- 使ç¨äºchanåæä»ä¹å¥½å¤åï¼
- æä¹æè½æ£ç¡®ç使ç¨chanå¢ï¼
æ们å ç第ä¸ä¸ªé®é¢ï¼ä¼æå¨ç¥ å¨goä¸chanæ¯ç¨æ¥å¤ä¸ªåç¨ä¹é´è¿è¡éä¿¡çï¼chançåºç¨æç»´æ¯ä¸ç§ç±»ä¼¼ä¸client/servierçæç»´ãä¹å°±æ¯è¦æä¿¡æ¯çç产è åæ¶è´¹è ãæ¢ç¶å¦æ¤ï¼é£å°±ä¼è®¾è®¡å° ä¸éåç¨ä¹é´çéä¿¡ï¼èå¨é¡ºåºç¼ç¨ä¸æ¯ä¸ä¼è®¾è®¡å°éä¿¡çï¼æ¯ä¸ç§çº¿æ§çæµç¨ã类似ä¸ä¸å¾ï¼
å¨å¾ä¸ï¼æ们çå°ï¼ç产è åæ¶è´¹è ä¹é´çç¨åºéè¿éä¿¡æ¥è¿è¡ç¸äºå½±åçï¼è线æ§çç¨åºæ¯ä¸ä¼æè¿ç§é®é¢ï¼ä¸ç®¡è°ç¨äºå¤å°å½æ°ï¼é½åªä¼å¨ä¸æ¡è¿ç¨ä¸é¡ºåºè¿è¡ã
å¨ä¸æä¸æ们ä¼ç¨å°ä¸ä¸ªä¸é´è çæ¦å¿µãä¸é´è æ¯æ¿æ¥ä¸æ¸¸çæ¶è´¹è åå¼å¯ä¸æ¸¸çç产è ã
åä¸é´è
åä¸é´è ï¼å°±æ¯å¨ç¨åºä¸åªæä¸ä¸ªçº¿ç¨è¿æ¥ç产è åæ¶è´¹è ï¼ä¸ä¼è¿è¡æ©å¢ã
å¦ä¸å¾æ示ï¼
å¨è¿ç§æ¹å¼ä¸ï¼åªæä¸ä¸ªä¸é´è ï¼æè 没æä¸é´è ã
- gen.go
func gen(nums ...int) <-chan int {
out := make(chan int)
go func() {
for _, n := range nums {
out <- n
}
close(out)
}()
return out
}
åæï¼å建ä¸ä¸ªoutçééï¼å¹¶æå¼ä¸æ¡åç¨å°numséè¿å¾ªç¯ä¼ éç»ééoutï¼å¨ææçnumsé½ä¼ å ¥outåå ³éééãå¨æå¼åç¨åè¿åå建çoutã
è¿ä¸ªå½æ°å¨ç¨åºä¸èµ·çç产è çä½ç¨ï¼ç产è åæ¶è´¹è¿ä¹é´ç交æµééå°±æ¯è¿ä¸ªoutï¼å½outä¸æ¶è´¹ä¸ä¸ªæ°åï¼æ¬å½æ°å°±ä¼åå°ä¸ä¸ªæ°æ¨éå°ééoutä¸ã
- sq.go
func sq(in <-chan int) <-chan int {
out := make(chan int)
go func() {
for n := range in {
out <- n * n
}
close(out)
}()
return out
}
å建äºééoutä½ä¸ºç产è çä¿¡æ¯è¾åºï¼å¹¶æ¥åinä½ä¸ºæ¶è´¹è çä¿¡æ¯è¾å ¥ã
è¿ç¨åºä¸ï¼å³æ¯æ¶è´¹è ä¹æ¯ç产è ï¼å¹¶å¨ä¸é´è¿è¡äºæ°æ®çå¤çnnãä½ä¸ºæ¶è´¹è ï¼å½ééinä¸å¯ä»¥åæ°æ®çæ¶åï¼ååºn并è¿è¡è¿ç®nnï¼ç¶åä½ä¸ºç产è å°ç»ææ¨éå°outä¸ãå½inä¸æå¼æ¶ä¼è¿è¡æ¶è´¹ï¼å¹¶è®¡ç®nn,å½out为空æ¶ä¼è¿è¡ç产ï¼å°nnçç»ææ¨å°outä¸ã
- main.go
func main() {
in := gen(2, 3)
c1 := sq(in)
for n := range c1 {
fmt.Println(n) // 4 9
}
}
mainå½æ°å è°ç¨äºä¸é¢ä¸¤ä¸ªå½æ°ï¼ç¶åç¨äºä¸ä¸ªå¾ªç¯è¿è¡è¾åºã
è¾åºè¿ä¸ªå¾ªç¯å°±æ¯æ´ä¸ªç¨åºçæ¶è´¹è ï¼å½c1ä¸æå¼æ¶ï¼å°±ä¼ååºæ¥æ¾å°nä¸ã
åä¸é´è 并ä¸è½ä½ç°ä½¿ç¨chançä¼è¶æ§ï¼æ´ä¸ªè¿ç¨ä»ç¶æ¯ç±»ä¼¼äºçº¿æ§çæµç¨è¿è¡ãå¨ä¸æä¸æ们ä¼å¼å¯å¤ä¸ªä¸é´è è¿è¡å¤æçæ°æ®è¿ç®åå¤çï¼å 为æ们å¯ä»¥åæ¶å¤çå¤æ¡æ°æ®ï¼å¿ ç¶ç»æ们带æ¥æ§è½ä¸çæé«ã
å¤ä¸é´è
åä¸é´è ï¼å°±æ¯å¨ç¨åºä¸åªæä¸ä¸ªçº¿ç¨è¿æ¥ç产è åæ¶è´¹è ï¼ä¸ä¼è¿è¡æ©å¢ã
å¨ä¸å¾ä¸ï¼ä¸ä¸ªç产è 被å¤ä¸ªä¸é´è å¤çç产çä¿¡æ¯ï¼ä»¥æé«æ¶è´¹çæçãç¶åç¨ä¸ä¸ªmergeçä¸é´è æ¶éå个ä¸é´è ç产çä¿¡æ¯ï¼å¹¶å°è¿äºä¿¡æ¯ç»ä¸ç交ç»æ¶è´¹è ã
- merge.go
func merge(cs ...<-chan int) <-chan int {
var wg sync.WaitGroup
out := make(chan int)
// Start an output goroutine for each input channel in cs. output
// copies values from c to out until c is closed, then calls wg.Done.
output := func(c <-chan int) {
for n := range c {
out <- n
}
wg.Done()
}
wg.Add(len(cs))
for _, c := range cs {
go output(c)
}
// Start a goroutine to close out once all the output goroutines are
// done. This must start after the wg.Add call.
go func() {
time.Sleep(222 * time.Second)
wg.Wait()
close(out)
}()
return out
}
è¿ä¸ªmergeå½æ°ç»æ带æ¥äºå¾å¤§çå°æ°ã
- ç¨åºä¸æ两个for循ç¯ï¼å ¶ä¸å¯¹csç循ç¯æ¯é对æ°ç»çï¼å¾ªç¯çä½ç¨æ¯å¯¹æ¯ä¸ªééæå¼ä¸ä¸ªåç¨ãèåç¨ä¸ç循ç¯æ¯çæ§ééç¨çï¼å½éécloseæ¶æ¨åºå¾ªç¯ã
为ä»ä¹wg.Waitè¦ç¨ä¸ä¸ªæ°çåç¨æ¥ï¼å¦æä¸ç¨æ°çåç¨èåå¨å½æ°ä½éé¢ä¸è¡åï¼å½ç¶æ¯ä¸è¡çï¼è¿éè¦æ³¨æä¸ä¸ªä¸æ®éç¨åºçåå«ï¼å¨ä½¿ç¨chançç¨åºä¸ï¼ä¸»ç¨åºçä½ç¨ç±»ä¼¼ä¸åå§åserviceåclientèä¸è¿è¡å ·ä½çè¿ç®ï¼æ以è¯å®ä¸è½å¨åå§åçæ¶åè¿è¡waitï¼å 为è¿éè¿æ¯è¦è¿è¡ç产ï¼å¦æè¿è¡waitå°±ä¸ä¼è¿è¡mainä¸çprintï¼ä¹å°±æ¯æ¶è´¹è ï¼ï¼èééå çæ°æ®ä¸è¿è¡æ¶è´¹å°±ä¼å½¢æé»å¡ï¼å¯¼è´ç¨åºæ æ³è¿è¡ã
*é£æå·²ç»ç¥éäºä¸è½ç¨å¨å½æ°ä½éé¢ï¼ä¸ºä»ä¹æå¦èµ·ä¸æ¡åç¨ï¼ä¸ä¼åºé®é¢å¢ï¼ï¼ è¿æ¶åå°åé¢é¨åï¼å¦æä½ æç½äºç¨åºè¿è¡çæ´ä¸ªæµç¨ï¼è¯å®å¯ä»¥è§£å³è¿ä¸ªçé®ï¼æ们æè¿ä¸ªé®é¢çå°åé¢è§£å³
- main.go
func main() {
in := gen(2, 3)
// Distribute the sq work across three goroutines that both read from in.
c1 := sq(in)
c2 := sq(in)
// Consume the merged output from c1 and c2.
for n := range merge(c1, c2) {
fmt.Println(n) // 4 then 9, or 9 then 4
}
}
å¨å½æ°ä¸å ç¨ç产è ï¼éè¿ééä¼ é两个æ°ï¼ç¶åç¨ä¸¤ä¸ªsqä¸é´è è¿è¡ä¸é´è®¡ç®ï¼ç¶åç¨mergeè¿è¡éåï¼æåéè¿printè¿è¡æ¶è´¹ã
å¨å次çå°è¿ä¸ªç¨åºçæ¶åï¼ææ¯è§å¾ç¨åºä¸ä¼è¾åºææçç»æççï¼ä¸ºä»ä¹æä¼è¿ä¹çå¢ï¼å 为å¨mergeä¸çwaitæ¯å¨å¦èµ·çä¸ä¸ªåç¨ä¸è¿è¡çï¼èä¸æ¯å¨ä¸»ç¨åºä¸ãå¦æä¸è½çæ¸ æ¥æ´ä¸ªç¨åºçæµç¨å°±ä¼ç¬¬ä¸æ¶é´åºç°è¿ç§è¯¯è§£ãé£æ们åªæ模æç¨åºä¸æ¥ä¸æ¥çè¿è¡ï¼æ¥å¤æ为ä»ä¹è¿ä¸ªç¨åºå¯ä»¥é¡ºå©çè¿è¡ã
æµç¨å¾
å æ¤æç»äºä¸é¢çæµç¨å¾ï¼å¾ä¸æ 注äºç¨åºçstepãï¼ä¸éåç¨ä¹é´çstepæ¯å¯ä»¥éåçï¼
æ们æ¥è¿ä¸éä¸å¾çæ´ä¸ªæµç¨ï¼ä½ å°±åç°ç¨åºä¸çææçé®é½è¿åè解ãï¼è½ç¶æ们è¿é使ç¨äºå¤ä¸ªä¸é´è çæ¹å¼ï¼ä½æ¯å 为æä»¬ä» ä» æ¨¡æäºä¸ä¸ªæ°æ®è¾å ¥ï¼æ以åªå±ç¤ºä¸ä¸ªä¸é´è å°±å¯ä»¥è¡¨ç¤ºæ´ä¸ªæµç¨ï¼
æµç¨å¾åæ
step 0ï¼
[main] è°ç¨ç¨åº gen(3)
step 1ï¼
[gen] å®ä¹éé out
step 2ï¼
step 3ï¼
[gen] è¿å ¥åç¨sub(gen)ä¸ç循ç¯ï¼å¤æ循ç¯æ¯å¦ç»æï¼åæ¶return out
step 4ï¼
[main] è¿å ¥ç¨åºsq
[sq] å®ä¹ééoutï¼genä¸çoutå®ä¹ä¸ºin
[sub(gen)] n-> out ##å 为è¿æ²¡æéå°æ¶è´¹è ï¼æ以é æäºé»å¡
step 5ï¼
[sq]è¿å ¥åç¨sub(sq)ä¸ç循ç¯ï¼å¤æ循ç¯æ¯å¦ç»æï¼åæ¶return out
step 6ï¼
[main] è¿å ¥ç¨åºmerge
[merge] wg.Add(1)并å¤æcs[]循ç¯æ¶åç»æ
[sub(sq)] ä»inä¸ååºæ°nï¼å¹¶è®¡ç®n*n,ç¶åä¼ å ¥ééout ##è¿æ¶inééä¸é»å¡ out ééé»å¡
step 7ï¼
[sub(gen)] outä¸åé»å¡ï¼å¤æ循ç¯æ¯å¦ç»æ
[merge] å¤æ循ç¯æ¯å¦ç»æï¼å¦æ没ç»æï¼è¿å ¥sub(merge),ç»æè¿å ¥sub(wait)
step 8ï¼
[sub(gen)] å¤æ循ç¯ç»æï¼close(out)
[sub(merge)]å¤æä¼ å ¥çééæ¯å¦å ³éï¼
[sub(wait)] å¤æmergeåç¨æ¯å¦é½å·²ç»è¿è¡ç»æ,没æç»æï¼çå¾
[merge]return out è¿åmain
step 9ï¼
[sub(merge)] å¤æéécæªå ³éï¼å°c->outï¼ ##è¿éoutä¸çå¼æ²¡ææ¶è´¹ï¼é»å¡ãc被æ¶è´¹ä¸å¨é»å¡
[main] å¤æmergeè¿åçéétæ¯å¦å ³é
step10ï¼
[sub(sq)] outééå¼åï¼å¤æééinæ¯å¦å ³é
[main] éét没æå ³éï¼å¹¶è¾åºtï¼æ¤æ¶tééä¸å¨é»å¡
step11ï¼
[sub(sq)]inééå ³éï¼step8ï¼,close(out)ï¼åç¨ç»æ
[main] tä¸æ²¡æå¼ï¼ä¸è¿è¡æä½
[sub(merge)]outééä¸åé»å¡ï¼å¤æcééæ¯å¦å ³é
step12ï¼
[sub(merge)] cééå ³éï¼step11ï¼ close(out) åç¨ç»æ
step13ï¼
[sub(wait)]å 为step12ä¸åç¨ç»æï¼æ以close(out)
step14ï¼
[main]å¤æéétå ³éï¼step13ï¼ï¼ç»æç¨åº
æµç¨å¾æ»ç»
- åªæçå¾ ï¼é»å¡åè¾å ¥ï¼éé空å读åºæä¼é æåç¨è·³è¿ä¸äºstepã
- main主线ç¨å 为è¦çå°éétå ³éï¼ä¹å°±æ¯è¦çå¾ sub(wait)ç»æï¼èsub(wait)è¦çå°ææçåç¨ç»æï¼æ以è¯å®ä¸ä¼åç主线ç¨è·å®ä½æ¯åç¨è¿æ²¡æè·å®çæ åµã
æµæ°´çº¿ç¤ºæå¾
è¿æ¯å¯¹ goä¸å ³äºchanåºç¨çç¨åºåæ
æç« ä¸ä»£ç çæµæ°´æµæ°´çº¿ç¤ºæå¾ã
- æ们å设genï¼sqåprintæä½éè¦çæ¶é´åä½é½æ¯1ï¼
time | gen | sq | |
---|---|---|---|
1 | out:1 | ||
2 | out:2 | out: 1 | |
3 | out:3 | out: 4 | 1 |
4 | out:4 | out: 9 | 4 |
5 | out:5 | Out: 16 | 9 |
6 | out:6 | Out: 25 | 16 |
7 | out:7 | Out: 36 | 25 |
8 | out:8 | Out: 49 | 36 |
9 | close(out) | close(out) | done<- |
æ们å设genï¼sqåprint没ä¸ä¸ªå¤çæ¥éª¤æ¯ç¸åçï¼é£æ们就å¯ä»¥ææ¾ççå°ä¸ä¸ªæµæ°´çº¿çå½¢å¼ï¼èæåæ们ç»doneè¿ä¸ªééæ¨å ¥æ°æ®ï¼genï¼sqåæ¶å ³é并éåºã
- ä½æ¯å¨ç¨åºç主ä½è¿è¡é¨åï¼sqå½æ°é常éè¦æ´å¤çæ¶é´è¿è¡æ°æ®è¿ç®æå ¶ä»ç¸å ³çæä½ãæ们å设sqçéè¦2个æ¶é´åä½ã
time | gen | sq | |
---|---|---|---|
1 | 1 | ||
2 | 2 | 1 | |
3 | blocked | going | |
4 | 3 | 4 | 1 |
5 | blocked | going | waiting |
6 | 4 | 9 | 4 |
7 | blocked | going | waiting |
8 | 5 | 16 | 9 |
9 | close(out) | close(out) | done<- |
ç±äºsqéè¦2个æ¶é´åä½æ¥è¿è¡è¿ç®ï¼è¿å°±å¯¼è´äºä¸æ¸¸æ¹æ³genè¾åºééé»å¡ï¼åä¸æ¸¸æ¹æ³print读åééçå¾ ãå¢å äºæ¶é´çæ¶èã
- ç±äºsqéè¦æ¶è2个æ¶é´åä½æ以æ们å¼å¯2个sqå½æ°ï¼åæ¶ç¨ä¸ä¸ªmergeå½æ°å¤ç两个sqå½æ°çééè¾åºãå¦ä¸ï¼
time | gen | Sq1 | Sq2 | Merge | |
---|---|---|---|---|---|
1 | 1 | ||||
2 | 2 | 1 | |||
3 | 3 | Going | 4 | ||
4 | 4 | 9 | Going | 1 | |
5 | 5 | Going | 16 | 4 | 1 |
6 | 6 | 25 | Going | 9 | 4 |
7 | 7 | Going | 36 | 16 | 9 |
8 | 8 | 49 | Going | 25 | 16 |
9 | close(out) | close(out) | close(out) | close(out) | done<- |
å¨è¿ä¸ªæµæ°´çº¿ä¸ï¼ç¨äºä¸¤ä¸ªsqåä¸ä¸ªmergeä½ä¸ºä¸é´å½æ°æ¥è¿è¡æ°æ®å¤çãè¿æ ·åæ ·å¨9个æ¶é´åä½å æ们å¯ä»¥è¾åº4个å¼ï¼åæ¶ä¹ä¸ä¼é æé»å¡çè¡ä¸ºã
- æ¢ç¶è¿æ ·æ们å¼3个ééä¼å¦ä½å¢ï¼
time | gen | Sq1 | Sq2 | Sq3 | Merge | |
---|---|---|---|---|---|---|
1 | 1 | |||||
2 | 2 | 1 | ||||
3 | 3 | Going | 4 | |||
4 | 4 | Going | 9 | 1 | ||
5 | 5 | 16 | Going | 4 | 1 | |
6 | 6 | 25 | Going | 9 | 4 | |
7 | 7 | Going | 36 | 16 | 9 | |
8 | 8 | Going | 49 | 25 | 16 | |
9 | close(out) | close(out) | close(out) | close(out) | done<- |
è¿æ¶å¯ä»¥çåºï¼å¦æééå¼çå¤äºä¹åæ»ä¼æä¸é¨åéé没æå¤äºæ»¡è´è·è¿è½¬ï¼è¿æ ·ä¼å¢å æ们ç空é´æ¶èã
- èå¦æsqéè¦å为3个æ¶é´åä½å¢ï¼
time | gen | Sq1 | Sq2 | Sq3 | Merge | |
---|---|---|---|---|---|---|
1 | 1 | |||||
2 | 2 | 1 | ||||
3 | 3 | Going | 4 | |||
4 | 4 | Going | Going | 9 | ||
5 | 5 | 16 | Going | Going | 1 | |
6 | 6 | Going | 25 | Going | 4 | 1 |
7 | 7 | Going | Going | 36 | 9 | 4 |
8 | 8 | 49 | Going | going | 16 | 9 |
9 | close(out) | close(out) | close(out) | close(out) | done<- |
å¨è¿ä¸ªæµæ°´çº¿ä¸ï¼å¼ä¸ä¸ªééï¼åæ¶sqçå¤çæ¶é´æ¯3个æ¶é´åä½ï¼æ£å¥½æ¯ä¸ªåç¨é½å¨è¿è½¬ä¸ä¸ä¼é æé»å¡æçå¾ çç°è±¡ã
ç±æ¤å¯ç¥ï¼æ们å¨ä¸ä¸ªpipelineä¸ï¼å ¶ä¸çä¸ä¸ªé¨åæ¯å¦å¹¶è¡ä¸»è¦æ ¹æ®ååç¨åºè¿è¡ä¸æ¬¡çæ¶é´æ¥å¤æï¼è¿è¡æ¶é´è¶é¿ï¼è¶åºè¯¥ç¨å¤ä¸ªåç¨å¤çã
ç¨ææå¾è¿è¡è¡¨ç¤ºï¼
æ´ä½æ»ç»
使ç¨goå°±ä¸å¯é¿å çè¦ç¨å°åç¨åééï¼èå¿çåææ¯å好代ç çåºç¡ãå½ä¸äºè§£ç¨åºçè¿è¡è¿ç¨æ¶ï¼æ们éè¦å°½å¯è½æ¸ æ°çæ´çç¨åºè¿è¡çæµç¨ã
å¨ç解äºç¨åºçè¿è¡åçä¹åï¼å°±å¯ä»¥æ ¹æ®å®é æ åµåæå¨ä»ä¹æ¶å使ç¨å¤ä¸ªä¸é´è ï¼ä½¿ç¨å¤å°ä¸ªä¸é´è ï¼æä¹è¿è¡æ¶æçãï¼ä¸é¢ä¼ç»åºä½¿ç¨å¤ä¸é´è çä¸ä¸ªç¨å¾®å¤æä¸ç¹ç代ç ï¼è¿æ¶æå¨å·¥ä½ä¸ä½¿ç¨çä¸ä¸ªgoçèæ¬ï¼
ä¹åçé®é¢æ¯å¦å·²ç»è¿åè解
- 为ä»ä¹æ´ä¸ªç¨åºå¨ä¸»ç¨åºä¸æ²¡æçå¾ åç¨ç¨åºç»æç类似wg.Waitçè¯å¥ï¼ä»ç¶ç¨åºå¯ä»¥æ£ç¡®çè¾åºï¼
- 为ä»ä¹å¨mergeä¸wg.Waitæ¯éè¦å¦å¤èµ·ä¸ä¸ªåç¨ï¼èä¸æ¯å¨å½æ°ç主ç¨åºä¸è¿è¡waitï¼
- make(chan int)åmake(chan int ,1)çåºå«ï¼å¨æ¬ç¨åºä¸è½æææçchan声æä»åè æ¢æåè åï¼
- æ¬ç¨åºæ¯æphpçä¸ä¸ªæ°ç»éè¿ä¸å®çæ å°å ³ç³»ï¼è½¬æ¢ä¸ºjsonæ ¼å¼çå符串ï¼å¹¶ä¿åå°æ件ä¸ã
æ´å¤é 读
- 并åä¸å¹¶è¡ä¸å åè§é¢
- pipeline(è¿æ¯æç« ä»£ç åºå¤ï¼åç»ä¼æç¿»è¯çæ¬
- [ç¿»è¯]Go并å模å¼ï¼æ建åç»æ¢æµæ°´çº¿
- go pipelineçæµæ°´çº¿ç¤ºæå¾
package main
import (
"encoding/json"
"errors"
"fmt"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
"io/ioutil"
"regexp"
"strings"
"sync"
)
var php = `
[
'è½ç¾å人' => ['first_id' => 2, 'name' => '纯ç±å°è¯´', 'third' => 'ç¾å纯ç±'],
'æ¬çæ¨ç' => ['first_id' => 2, 'name' => 'æ¬ççµå¼', 'third' => 'ææææ'],
]
`
type Item struct {
FirstID int `json:"first_id"`
Name string `json:"name"`
Third string `json:"third"`
}
type CategoryReplaceMap struct {
ID int `json:"id"`
Before string `json:"before"`
After string `json:"after"`
}
type Result struct {
CopyrightCateGory string `json:"copyright_category"`
First *CateGoryField `json:"stack_first_category_id"`
Second *CateGoryField `json:"stack_second_category_id"`
Third *CateGoryField `json:"stack_third_category_id"`
}
type Response struct {
CopyrightCateGory string `json:"copyright_category"`
First int `json:"stack_first_category_id"`
Second int `json:"stack_second_category_id"`
Third int `json:"stack_third_category_id"`
}
type CateGoryField struct {
Name string `json:"name"`
Parent int `json:"parent"`
Rank int `json:"rank"`
ID int `json:"id"`
}
func main() {
phpMap, err := parseToMap()
if err != nil {
fmt.Println("解ææmapé误")
return
}
response := make(map[string][]Response)
s := product(phpMap)
v := make([]<-chan *Response, len(phpMap))
for i := 0; i < len(phpMap); i++ {
v[i] = middle(s)
}
out := merge(v)
for item := range out {
response["category_mappers"] = append(response["category_mappers"], *item)
}
findNotMap(phpMap, response)
resultJson, err := json.Marshal(response)
ioutil.WriteFile("test.json", resultJson, 0777)
fmt.Println(string(resultJson), err)
}
func parseToMap() (map[string]*Item, error) {
var phpMap = make(map[string]*Item)
rePlaceMap, err := getReplaceMapFromDB()
if err != nil {
fmt.Println(err)
}
fmt.Println("åç±»æ¹åç对åºå
³ç³»")
for k, v := range rePlaceMap {
fmt.Println(k, v)
}
phpjson := strings.ReplaceAll(php, " ", "")
for k, v := range rePlaceMap {
phpjson = strings.ReplaceAll(phpjson, k, v)
}
phpjson = strings.Replace(phpjson, "=>", ":", -1)
phpjson = strings.Replace(phpjson, "'", "\"", -1)
phpjson = strings.Replace(phpjson, "[", "{", -1)
phpjson = strings.Replace(phpjson, "]", "}", -1)
reg1 := regexp.MustCompile(`([\d]+) *:`)
if reg1 == nil {
fmt.Println("regexp err")
return nil, errors.New("å¹é
模å¼é误1")
}
//æ ¹æ®è§åæåå
³é®ä¿¡æ¯
phpjson = reg1.ReplaceAllString(phpjson, `"${1}" :`)
reg2 := regexp.MustCompile(`(}),(\n *})`)
if reg2 == nil {
fmt.Println("regexp err")
return nil, errors.New("å¹é
模å¼é误1")
}
//æ ¹æ®è§åæåå
³é®ä¿¡æ¯
phpjson = reg2.ReplaceAllString(phpjson, `${1}${2}`)
fmt.Println(phpjson)
err = json.Unmarshal([]byte(phpjson), &phpMap)
fmt.Println(err)
return phpMap, err
}
//productæ¯ææ£å¸¸çè¾å
¥ä¼ å
¥ééï¼
func product(in map[string]*Item) <-chan map[string]*Item {
out := make(chan map[string]*Item)
go func() {
for k, v := range in {
out <- map[string]*Item{k: v}
}
close(out)
}()
return out
}
//middle æ¯ä¸ä¸ªå¤çæ°æ®çå½æ°ï¼
func middle(in <-chan map[string]*Item) <-chan *Response {
out := make(chan *Response)
go middleHand(in, out)
return out
}
func middleHand(in <-chan map[string]*Item, out chan *Response) {
for aMap := range in {
res := &Response{}
for k, v := range aMap {
dbRes := getDBByNameRes(v.Third)
wg := sync.WaitGroup{}
for _, item := range dbRes {
wg.Add(1)
go func(item *CateGoryField) {
defer func() {
wg.Done()
if err := recover(); err != nil {
fmt.Printf("book, panic: %+v\n", err)
}
}()
resultItem := &Result{}
resultItem.CopyrightCateGory = k
getResult(item, resultItem)
if resultItem.First.ID == v.FirstID && resultItem.Second.Name == v.Name {
responseItem := &Response{}
responseItem.CopyrightCateGory = resultItem.CopyrightCateGory
responseItem.First = resultItem.First.ID
responseItem.Second = resultItem.Second.ID
responseItem.Third = resultItem.Third.ID
res = responseItem
}
}(item)
}
wg.Wait()
}
out <- res
}
close(out)
}
//mergeæ¯æmiddleçè¾åºæ´ååä¼ å
¥ä¸ä¸ªéé
func merge(in []<-chan *Response) <-chan *Response {
out := make(chan *Response)
wg := sync.WaitGroup{}
output := func(c <-chan *Response) {
for n := range c {
out <- n
}
wg.Done()
}
for _, i := range in {
wg.Add(1)
go output(i)
}
go func() {
wg.Wait()
close(out)
}()
return out
}
func getResult(item *CateGoryField, resultItem *Result) {
if item.Rank == 1 {
resultItem.First = item
}
if item.Rank == 2 {
resultItem.Second = item
dbRes := getDBByID(item.Parent)
getResult(dbRes, resultItem)
}
if item.Rank == 3 {
resultItem.Third = item
dbRes := getDBByID(item.Parent)
getResult(dbRes, resultItem)
}
}
func getReplaceMapFromDB() (map[string]string, error) {
res := []*CategoryReplaceMap{}
db, err:= connectDB("distribution_w:********@tcp(rm-******.mysql.******.rds.aliyuncs.com:3306)/content_distribution?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil{
return nil,err
}
err = db.Table("category_change").Find(&res).Error
if err != nil {
fmt.Println("æ¥è¯¢æ°æ®åºå¤±è´¥")
return nil, err
}
response := make(map[string]string)
for _, item := range res {
item.Before = strings.ReplaceAll(item.Before, "\n", "")
item.After = strings.ReplaceAll(item.After, "\n", "")
item.Before = strings.ReplaceAll(item.Before, " ", "")
item.After = strings.ReplaceAll(item.After, " ", "")
response[item.Before] = item.After
}
return response, nil
}
func getDBByNameRes(name string) []*CateGoryField {
res := make([]*CateGoryField, 0)
//res:= execsql(sql)
db, err:= connectDB("distribution_w:********@tcp(rm-******.mysql.******.rds.aliyuncs.com:3306)/content_distribution?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil{
return nil
}
err = db.Table("category").Where("name = ? ", name).Find(&res).Error
if err != nil {
fmt.Println("æ¥è¯¢æ°æ®åºå¤±è´¥")
return nil
}
return res
}
func getDBByID(id int) *CateGoryField {
res := &CateGoryField{}
db, err:= connectDB("distribution_w:********@tcp(rm-******.mysql.******.rds.aliyuncs.com:3306)/content_distribution?charset=utf8mb4&parseTime=True&loc=Local")
if err != nil{
return nil
}
err = db.Table("category").Where("id = ? ", id).Find(&res).Error
if err != nil {
fmt.Println("æ¥è¯¢æ°æ®åºå¤±è´¥")
return nil
}
return res
}
func connectDB(connect string) (*gorm.DB, error) {
db, err := gorm.Open("mysql", connect)
if err != nil {
fmt.Println("è¿æ¥æ°æ®åºå¤±è´¥")
return nil,err
}
return db,nil
}
func findNotMap(phpMap map[string]*Item, response map[string][]Response) {
for k := range phpMap {
var yn bool
for _, v := range response["category_mappers"] {
if k == v.CopyrightCateGory {
yn = true
break
}
}
if yn {
continue
}
fmt.Println(k, phpMap[k], " not in the category_mappers")
}
}