Golang 學習筆記 Day 0 - Why Golang & 安裝篇

免責聲明,此篇為個人學習筆記,非正式教學文,僅供參考感謝指教,有任何內容錯誤歡迎發 issue。 Why Golang 在高中時期,除了一年級上學期是用 C 打開程式大門之外,大家都知道的,畫金字塔、 cin 、 cout 等等基本的邏輯觀念,一年級下學期開始就是 C#、HTML、PHP,也玩轉在 CPLD、Arduino、焊三角錐、兩根同軸焊接,總之就是全部吃掉就對了,雖然都是皮毛但不至於完全沒印象。 然而到了大學,敝人不才沒有考上一般大學,也沒考上工科第一二志願科大,在整個大學過程碰了最多的反而是 python、machine learning。然而也都是碰皮毛因為都在玩社團、學攝影,事實上在大學時期程式功力已荒廢大半。 所幸在實習期間,公司願意提供環境讓我邊學習邊成長後做出貢獻,而使用的後端語言是 PHP,然而就一年以來的使用 PHP 有以下優缺點: 學習曲線極低,但坑很多 解釋型腳本語言部署極方便 非靜態、非強行別、萬用 array 導致容易出現很多偷懶的 code 窮人聖經 LAMP、LNMP 歷史悠久 framework 眾多、工作好找,甚至有許多 C 底層的高校框架可以使用。 可以很 OO 也可以不 OO,寫 code 彈性極大 在 php 7.0 改用 zend 引擎後效能改頭換面,「原來 PHP 也可以寫遊戲」。搭配一些 C 底層框架,甚至可以跟 nodeJS 一較高下,而期望中 8.0 效能將再更高。 但是,再快也只是 AE86,腳本語言終究與「高效」存在矛盾,同時,與其在 PHP 中配合 IDE 使用 type hinting 自我約束,何不直接寫強行別語言呢?? 然而在看過許多主流 web service 語言後,最後決定來學學 Golang,而關於 golang 的優勢,可以點擊下方圖片看更多詳細。 ...

Golang 學習筆記 Day 1 - Getting started

免責聲明,此篇為個人學習筆記,非正式教學文,僅供參考感謝指教,有任何內容錯誤歡迎發 issue。 在前一天介紹了為何要使用 golang、安裝過程以及基本的 hello world,這天將重點放在最基本的 golang 程式碼特徵。 packages 正如昨天關於 hello world 的解析中提到的,每個程式都是由一到多個 packages 組成的,也就是 .go 中必須宣告該檔案是哪個 package,且同一個資料夾中僅接受 xxx 以及 xxx_test 兩種 package名稱,也就是該 package 的名稱以及測試檔的「測試包」。 至於 package 要怎麼命名呢,首先要提到檔案該如何命名,雖然 go format 是對於程式碼風格十分嚴格的,但是對於檔案名稱似乎就沒那麼嚴謹,但整個社群中普遍會用 snake_case 或是 dash-case 作為檔案 (甚至是 package) 的命名。 aaabbbccc.go time-machine.go battery_charger.go 但是需要注意的是 go build 會忽略所有以 _ 或是以 . 作為結尾的後綴, underline 可能會導致在建構時被忽略。 再來提到 package 到底要如何命名呢,官方文檔中明確的提到不要用 camelCase 以及 snake_case 。 The style of names typical of another language might not be idiomatic in a Go program. Here are two examples of names that might be good style in other languages but do not fit well in Go: ...

RESTful server based on golang

很高興有個機會製作面試前的測試作業,也就趁這個機會做個筆記以及學習紀錄。 前置作業 先點列一下項目需求: 基本需求 based on golnag The API interface you provide can be any of the following:RESTful、json rpc、gRPC At least two sources When a source is unavailable, the result of its last successful ask is returned Use git to manage source code Write readme.md and describe what features, features, and TODO which have been implemented 額外可選 Traffic limits, including the number of times your server queries the source, and the number of times the user queries you Good testing, annotations, and git commit An additional websocket interface is provided to automatically send the latest information whenever the market changes Users can choose to use an automatic source determination, the latest data source, or manually specify the source of the data Package it as a Dockerfile, docker-compose file, or kubernetes yaml There is a simple front-end or cli program that displays the results The API you provide has a corresponding file, such as a swagger, or simply a markdown file Other features not listed but that you thought would be cool to implement 這邊就必須要先打預防針了,這篇僅為學習筆記,並非正式教學。且,我只是 Golang 初學者,所以這篇內也不會出現什麼高等級的解法,甚至也是第一次實作介接 API 呢 (笑)。而 DB 以及 redis 都是直接以方便使用去寫 dbi 而已並無用抽象曾去封裝,也進而導致 unit test 十分困難先擱置了,有空才會再針對性重構,而此次就先將目標專注在 API 介接。 ...

Codewars Find X II in golang

想不到一眨眼半個月過去了,自從面試趨勢之後整個人彷彿被電到失去信心,在離職與等待面試消息期間,也只好振作補足不足的地方繼續向前。 而 docker 學習心得何時會產出呢?在學習過程中發現除了一般操作(day1 內容)外,底層或多 container 溝通都是大量的網路觀念與知識,需要更多知識量才能整理成筆記,不急不急。 由於學習過程發現而這段時間在 coding 能力上主要還是靠 codewars 上的題目,畢竟解完後能看別人的 code 來檢視自己的 code 能不能更好。其中不免遇到一些覺得很有趣的題目,好比這題 Find X II,他並不是什麼過分難的題目,邏輯也不是很難通,畢竟只是一個 6 kyu 的題目,但為何快一年了只有 44 個人解完呢,這就牽扯到下面要說的。 題目概要 有下一段程式碼: func FindX(n int) int { if n == 0 { return 0 } x := 0 for i:=1; i<=n; i++ { x += FindX(i-1) + 3*i } return x } 但 x 範圍為 1 <= n <= 10**6(1e6) ,請試著重構。且當 n 愈來試大時,可能會超過 int64 表達,故需要將結果對 10**9 + 7 取模 標記 FUNDAMENTALS OPTIMIZATION 解題邏輯 若沒有取模限制的話這題可以化簡為 O(1),但很明顯不行。於是先將原題目化簡為 O(n): func FindX(n int) int { mod := int(math.Pow10(9)) + 7 m := 0 for i := 0; i <= n; i++ { m = (m*2 + 3*i) % mod } return m } 好測試過,就算是輸入 1e6 進去也很快就算出來了,於是提交答案 ...

威康生命遊戲 in PHP

威康生命遊戲 in PHP 生命遊戲,無論在程式、哲學、生命探討上都十分有趣,在生命遊戲中甚至出現永動機。而在 Codewars 中也有生命遊戲的 題目,規則也十分簡單,以下為維基百科的內容: 1. 每個細胞有兩種狀態 - 存活或死亡,每個細胞與以自身為中心的周圍八格細胞產生互動(如圖,黑色為存活,白色為死亡) 2. 當前細胞為存活狀態時,當周圍的存活細胞低於2個時(不包含2個),該細胞變成死亡狀態。(模擬生命數量稀少) 3. 當前細胞為存活狀態時,當周圍有2個或3個存活細胞時,該細胞保持原樣。 4. 當前細胞為存活狀態時,當周圍有超過3個存活細胞時,該細胞變成死亡狀態。(模擬生命數量過多) 5. 當前細胞為死亡狀態時,當周圍有3個存活細胞時,該細胞變成存活狀態。(模擬繁殖) 若想知道關於更多可以觀看上方由混亂博物館出品的影片,此篇就針對這 4kyu 的題目進行探討解法。首先題目中指出這個宇宙的 x,y 軸都是無限大的,所以生成高斯帕機槍且迭代過多次可能造成記憶體使用過量。 迭代 首先題目給定一個二維矩陣以及迭代次數(世代),而需取得過了該迭代次數後的情形。 function get_generation(array $cells, int $generations): array { if($cells == []) return [[]]; $w = count($cells); $h = count($cells[0]) for ($index = 0; $index < $generations; $index++) { $cells = getNextGen($cells, $w, $h); $sum = 0; foreach ($cells as $row) { $sum += array_sum($row); } if ($sum == 0) { return [[]]; } } return $cells; } 於是可以建立一個方法 getNextGen 來獲取下個世代的結果 ...

VScode SFTP 快速同步文件到 Server

當 Server 環境使用白名單搭配 Reverce-Proxy 時,或是 dev、test 環境不供外部使用時,或許會將部分 code 存在只能靠內網連線的主機上,並透過 OpenSSH 供內部遠端操作。 而 PHP 快速部屬的便捷在於替換單一檔案不須重啟 Server (前提是並非把檔案載進 Memory 或轉化守護進程),此時可以依靠 FTP 上傳單一檔案即好。但每次改個 code 還要想辦法上傳程式碼實在是太浪費時間了,如標題所述,如何快速同步 code 到 Server 上呢。 vscode-sftp 是一個在 VScode 中非常方便的擴充套件,上傳/下載/同步、單一/多伺服器、ftp/sftp,僅需設置一份或多份的設定檔便能(偷懶不切視窗)上傳檔案到 Server。然而正是環境 (production) 還是走正常 CI/CD 比較好。 安裝 首先在 VScode 中的市集,或是快捷鍵 ctrl+shift+P (或 F1) 打開指令窗口後輸入 extension:install。並搜尋 SFTP,認名作者 liximomo 點一下玩一年,上傳不花一分錢(支持者可以拉到下面點選 donate)。 設定上傳環境/參數 接著同樣打開指令窗口並輸入 SFTP: Config 注意由於是 JSON 格式,不能註解 主要配置好host, port, username, privateKeyPath, remotePath, ignore这参数即可: name : 檔案暱稱 host : server IP/URL port : 若 server 建置好 ssh 環境,可將 port 端口改為 22 username : 在 server 中的使用者名稱 remotePath : 欲上傳的目錄位置 privateKeyPath : 私鑰 password : 若有設私鑰則可有(null)可無 uploadOnSave : 自動上傳,個人是沒有開啟(經常性按 ctrl + S) ignore : { "name": "my_work_space", "host": "192.168.X.X", "port": 22, "protocol": "sftp", "username": "centos", "remotePath": "\\home\\centos\\***\\", "privateKeyPath": "C:\\***.pem", "uploadOnSave": false, "syncMode": "update", "ignore": [ "**/.vscode/**", "**/.git/**", "**/.svn/**", "**/.DS_Store" ] } 同步所有檔案 儲存後按下同樣打開指令窗口並輸入「SFTP: Sync Local -> Remote」,再選取剛剛設定中的 name(ex.my_work_space) 便可以重部整份資料夾/工作區到遠端伺服器上囉。 ...

Evaluate mathematical expression in PHP

四則運算,不多,不就是加減乘除而已嗎,怎麼會在 Codewars 中被標記為 2 kyu 的題目呢? 總覺得這篇標題應該改為「Codewars 從入坑道棄坑,只需要一題就搞定」。首先我是在 2019 年底才接觸 Codewars,這種打怪練功的感覺讓我一下就上癮了,每天都在想今天能不能再拚一階,或是這題用另外一個語言會不會比較省時間。直到遇到了這題,足足卡了一整天。下面就來介紹一下四則運算在 PHP 中的解法吧。 先乘除後加減,看到括號先做 先舉一個簡單的例子 a+b 該怎麼做呢,有學過一點資料結構的應該很快就會回想起「中序轉後序」。 首先會需要將引入的字串轉為中序 // 123 + 456 * -789 // => // ['123', '+', '456, '*', '-', '789'] function isOp(string $s): bool { return strpos("+-*/", $s) !== false ? true : false; } function changeStringToInfix(string $expression): array { $infix = []; $count = strlen($expression); for ($i = 0; $i < $count; $i++) { if (isOp($expression[$i]) === false) { $j = $i; while ($i < $count && (isOp($expression[$i]) === false)) { $i = $i + 1; } $infix[] = substr($expression, $j, $i - $j); $i = $i - 1; } else { $infix[] = substr($expression, $i, 1); } } return $infix; } 這時候可能有眼尖的會發現,不對阿中序怎麼可以兩個運算子(’*’, ‘-’)連在一起,恭喜你踩進四則運算第一個坑:負號可能是負號也可能是減號。於是可以使用一個偷吃步的方式,將運算子後的負號一率改成另一個代表負號的特殊符號,比如「@」。而這步可以使用正規表達式輕鬆辦到。 ...

PHP ENUM 偽實現

Enumerations 又可簡稱為 Enum ,在眾多語言中都可以讓程式碼更高效簡潔,例如我們可以在 python 中這麼宣告,並且用 requests 模組打一個 request,即可透過 Enum 來模組化 Response import enum import request class HTTPResponsecode(enum.Enum) OK = 200 BAD_REQUEST = 400 NOT_FOUND = 404 r = requests.get('https://omegaatt.com/') print(r.status_code == HTTPResponsecode.OK) # True 但是在 PHP 中原生是沒有內建 Enum 的,必須安裝 perl 的 SplEnum 類套件庫,方能直接使用 Enum 的功能。或是可以透過以下的方式達到接近的效果。 極簡易版 Enum 首先,建立一個 Enum 類,一樣舉例為 HTTP 的 response code abstract class HTTPResponsecodeEnum { const OK = 200; const BAD_REQUEST = 400; const NOT_FOUND = 404; } 這樣就完成最基本的 Enum 拉,只要透過簡單的 if 判斷便能輕鬆享受打包的方便 if($status_code == HTTPResponsecodeEnum::OK){ // foo(); } 具有驗證功能的 Enum 根據防禦性程式寫法,我們知道千萬不要相信使用者傳過來的東西,必須去驗證資料是否正確時,極簡版本已經無法勝任。這時候可以使用 ReflectionClass 這個這個類別協助,由這個類來取得 Class 中的常數。 ...