Pekerjaan - pola desain untuk pemula dan programmer Go yang berpengalaman

Saya memulai pemrograman di Go setelah cukup lama memprogram di PHP. Saya kira, dilihat dari tren terbaru, kasus saya jauh dari kasus terisolasi. Go secara umum semakin populer di kalangan pengembang Web.





Jadi, saya berada di dunia gopher. Dan apa yang dilakukan oleh programmer PHP, dibakar sampai ke intinya, begitu di sana? Itu benar, dia terus "engah" - karena deformasi profesionalnya - tetapi sudah di Go, dengan semua konsekuensi selanjutnya.





, Go , , SOLID, Dependency Injection . , ( ), , - PHP, ++ Java.





, , . context.Context, ? , PHP . - ! , , PHP , , Go. . , . , proof of concept. Go, .





, , , , : ", , . , ". — . Reddit Go , … . "? ? over-engineering" - . : " . , README.md - ".





Bagaimana programmer melihat solusinya

, , , .





? - . :





  1. Job - , (task).





  2. -, L4; , backend ; backend , . Job. Github.





Job - Command pattern, . :





Parallel Processing Where the commands are written as tasks to a shared resource and executed by many threads in parallel (possibly on remote machines; this variant is often referred to as the Master/Worker pattern)





, - — . , , context.Context, , . task.Assert



if err != nil { panic(err) }.







ping/pong . , — Github .





// Saves resized image to the output dir
func (s *ImageResizer) SaveResizedImageTask(j job.Job) (job.Init, job.Run, job.Finalize) {
	// Do some initialization here
	init := func(t job.Task) {
		if _, err := os.Stat(s.inputDir); os.IsNotExist(err) {
			t.Assert(err)
		}
		if _, err := os.Stat(s.outputDir); os.IsNotExist(err) {
			err := os.Mkdir(s.outputDir, 755)
			t.Assert(err)
		}
	}
	run := func(task job.Task) {
		stream := j.GetValue().(netmanager.Stream)
		select {
		case finishedTask := <- j.TaskDoneNotify(): // Wait for the scanner task to be done
			if finishedTask.GetIndex() == s.scanneridx {
				s.scandone = true
			}
			task.Tick()
		case frame := <-stream.RecvDataFrame(): // Process response from the backend server
			task.AssertNotNil(frame)
			res := &imgresize.Response{}
			err := frame.Decode(res)
			task.Assert(err)

			baseName := fmt.Sprintf("%s-%dx%d%s",
				res.OriginalName, res.ResizedWidth, res.ResizedHeight, res.Typ.ToFileExt())
			filename := s.outputDir + string(os.PathSeparator) + baseName
			if ! s.dryRun {
				ioutil.WriteFile(filename, res.ImgData, 0775)
			}

			j.Log(1) <- fmt.Sprintf("file %s has been saved", filename)
			stream.RecvDataFrameSync() // Tell netmanager.ReadTask that we are done processing the frame
			s.recvx++
			task.Tick()
		default:
			switch {
			case s.scandone && s.recvx == s.sentx: // Check if all found images were processed
				task.FinishJob()
			default:
				task.Idle() // Do nothing
			}
		}
	}
	return init, run, nil
}
      
      







Ini adalah salah satu tugas klien, yang memproses respons yang masuk dari server dan menyimpan gambar yang dihasilkan. Tugas mengatur eksekusinya - menggunakan teknik sinkronisasi ping / pong yang disebutkan di atas - dengan tugas yang melakukan pemindaian file. Ini juga menentukan kapan respons terakhir dari server datang dan kapan harus menyelesaikan eksekusi semua pekerjaan (Job).





Sejauh mana solusi ini over-engineered dan sejauh mana penggunaannya, bukan konteks. Konteks dibenarkan - biarkan pembaca memutuskan, saya mengutarakan pendapat saya dalam bentuk sarkasme pada gambar di atas.





Semoga akhir pekan Anda menyenangkan semua orang dan semoga kekuatan pehape menyertai kita di dunia gophers.








All Articles