﻿# 比對字串在不同程式語言的語法差異 (JS, C#, Java, Go)

今天同事提到一個問題，說他看到客戶用 JavaScript 的 `<` 或 `>` 來比對日期字串，但我們要將這份邏輯移到後端 Java 應用程式中，由於 Java 沒看到類似的語法，雖然知道有 Java 字串有個 `compareTo()` 方法可用，但不知道差異在哪裡，也深怕有個未知的地雷會踩到。因為這個需求，我今天寫了 4 種不同程式語言的字串比對差異比較，看的懂程式碼的話，未來應該就知道這幾種語言字串比對的差異在哪裡了。

1.  JavaScript (Jasmine)
    
    所有 JavaScript 字串 (string) 主要使用 **UTF-16** 編碼！
    
    ```javascript
    it('2021/06/28 > 2021/06/27', () => {
        let a = '2021/06/28';
        let b = '2021/06/27';
    
        expect(a > b).toBeTrue();
        expect(a === a).toBeTrue();
        expect(b > a).toBeFalse();
    });
    ```
    
    事實上在 JavaScript 裡面 **String** 的**原型物件**(prototype)還有一個 [localeCompare()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) 方法，而且功能還不少，因為這個方法包含了 **地區資訊**(locale) 的判斷邏輯。不過如果你只是要比對基礎 ASCII 字元的話，其實沒有什麼差別。
    
    ```javascript
    it('2021/06/28 > 2021/06/27', () => {
        let a = '2021/06/28';
        let b = '2021/06/27';
    
        expect(a.localeCompare(b) > 0).toBeTrue();
        expect(a.localeCompare(a)).toBe(0);
        expect(b.localeCompare(a) < 0).toBeTrue();
    });
    ```
    
    > 注意：千萬不要比對 `-1` 或 `1` 的結果，要用 `> 0` 或 `< 0` 來做判斷！
    
2.  C# / .NET (xUnit)
    
    所有 .NET 字串 (String) 主要使用 **UTF-16** 編碼！
    
    ```csharp
    [Fact]
    public void Test1()
    {
        var a = "2021/06/28";
        var b = "2021/06/27";
    
        Assert.True(String.Compare(a, b) > 0, "2021/06/28 > 2021/06/27");
        Assert.True(String.Compare(a, a) == 0, "2021/06/28 = 2021/06/28");
        Assert.True(String.Compare(b, a) < 0, "2021/06/28 > 2021/06/27");
    }
    ```
    
    > 注意：千萬不要比對 `-1` 或 `1` 的結果，要用 `> 0` 或 `< 0` 來做判斷！
    
3.  Java (JUnit)
    
    所有 Java 字串 (String) 主要使用 **UTF-16** 編碼！
    
    ```java
    @Test
    public void whenAssertingConditions_thenVerified() {
        String a = "2021/06/28";
        String b = "2021/06/27";
    
        assertTrue("2021/06/28 > 2021/06/27", a.compareTo(b) > 0);
        assertTrue("2021/06/28 = 2021/06/28", a.compareTo(a) == 0);
        assertTrue("2021/06/28 > 2021/06/27", b.compareTo(a) < 0);
    }
    ```
    
    > 注意：千萬不要比對 `-1` 或 `1` 的結果，要用 `> 0` 或 `< 0` 來做判斷！
    
4.  Go
    
    所有 Go 字串 (string) 主要使用 **UTF-8** 編碼！
    
    ```go
    package main
    
    import "fmt"
    
    func main() {
      a := "2021/06/28"
      b := "2021/06/27"
    
      fmt.Println(a > b) // true
      fmt.Println(a == a) // true
      fmt.Println(b > a) // false
    }
    ```
    
    我另外為 Go 寫了一個自訂的 `String` 結構，並自訂 `CompareTo` 方法，試圖模仿 .NET / Java 的 API：
    
    ```go
    package main
    
    import "fmt"
    
    func main() {
      a := String("2021/06/28")
      b := String("2021/06/27")
    
      fmt.Println(a.CompareTo(b)) // 1
      fmt.Println(a.CompareTo(a)) // 0
      fmt.Println(b.CompareTo(a)) // -1
    }
    
    type String string
    
    func (a String) CompareTo(b String) int {
      if a > b {
        return 1
      }
      if b > a {
        return -1
      }
      return 0
    }
    ```
    

### 相關連結

-   [JavaScript | MDN](https://developer.mozilla.org/zh-TW/docs/Web/JavaScript)
-   [C# docs - get started, tutorials, reference. | Microsoft Docs](https://learn.microsoft.com/en-us/dotnet/csharp/?WT.mc_id=DT-MVP-4015686)
-   [Java Tutorial](https://www.w3schools.com/java/)
-   [The Go Programming Language Documentation](https://golang.org/doc/)
