Mở đăng ký khóa học Fullstack qua Zoom. Tham khảo tại đây

Thư Viện Câu Hỏi Phỏng Vấn

Tổng hợp các câu hỏi tuyển dụng thực tế theo nhiều cấp độ từ Entry đến Expert để bạn tự tin chinh phục nhà tuyển dụng.

Interactive Practice Tổng cộng 4,442 câu hỏi độc bản

Luyện Tập Phỏng Vấn Thử

Mô phỏng áp lực phỏng vấn thật với đồng hồ đếm ngược từng câu, tự đánh giá phản xạ và đo lường độ sẵn sàng của bạn.

Vui lòng đăng nhập để tham gia luyện tập và lưu tiến độ phỏng vấn.
1141

Input Object Types trong GraphQL là gì và tại sao chúng lại bắt buộc phải dùng cho Mutations?

Junior

Input Object Types là một loại Schema đặc biệt cho phép gom nhóm nhiều trường dữ liệu lại thành một cấu trúc phức tạp để truyền vào làm tham số (arguments) cho Queries hoặc Mutations.

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1142

Interface và Union trong GraphQL khác nhau như thế nào và khi nào nên dùng loại nào?

Junior

Cả Interface và Union trong GraphQL đều được sử dụng để định nghĩa các kiểu dữ liệu trừu tượng (Abstract Types), cho phép trả về nhiều Object Types khác nhau từ một trường duy nhất. Tuy nhiên, chúng có cơ chế hoạt động khác nhau:

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1143

Cơ chế hoạt động của panic, recover và defer trong Go lang diễn ra như thế nào và best practices khi xử lý lỗi ngoại lệ?

Junior

Bản chất cơ chế

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1144

Sự khác biệt giữa khai báo Slice và Array trong Go lang là gì và tại sao Slice lại được sử dụng phổ biến hơn trong thực tế lập trình?

Junior

Bản chất cơ chế

  • Array (Mảng): Có kích thước cố định được định nghĩa tại thời điểm biên dịch (compile-time). Kích thước là một phần của kiểu dữ liệu (ví dụ: [3]int khác với [5]int). Array được truyền theo dạng Pass by Value (sao chép toàn bộ phần tử khi gán hoặc truyền vào hàm).
  • Slice (Lát cắt): Là một cấu trúc dữ liệu động linh hoạt hơn, bao gồm 3 thành phần: Con trỏ trỏ tới mảng ngầm định (Pointer), Độ dài hiện tại (Length), và Sức chứa tối đa (Capacity). Slice là kiểu tham chiếu nhẹ.

Tại sao Slice phổ biến hơn?

  1. Kích thước linh hoạt, có thể mở rộng thông qua hàm dựng sẵn append().
  2. Tiết kiệm bộ nhớ khi truyền vào hàm vì chỉ copy cấu trúc descriptor 24 bytes gồm pointer, len, cap chứ không copy toàn bộ mảng dữ liệu bên dưới.

Ví dụ minh họa

// Khai báo Array cố định
var arr [3]int = [3]int{1, 2, 3}

// Khai báo Slice động
var slice []int = []int{1, 2, 3}
slice = append(slice, 4)

Lưu ý kinh nghiệm thực chiến

Khi dùng append() trên Slice, nếu vượt quá Capacity, Go sẽ tự động cấp phát một vùng nhớ mới lớn gấp đôi và copy dữ liệu sang. Cần lưu ý hiện tượng rò rỉ bộ nhớ (Memory Leak) khi slice con trỏ tham chiếu đến một mảng lớn ban đầu khiến Garbage Collector không thể giải phóng vùng nhớ đó.

1145

Làm thế nào để quản lý Context trong Go lang nhằm kiểm soát thời gian timeout và hủy bỏ (cancellation) các tác vụ bất đồng bộ?

Junior

Bản chất cơ chế

Package context trong Go lang được thiết kế để truyền tải tín hiệu hủy bỏ (cancellation signal), deadline, thời hạn timeout và các giá trị phạm vi yêu cầu (request-scoped values) qua các API ranh giới và giữa các Goroutines.

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1146

Sự khác biệt cốt lõi giữa Pass by Value và Pass by Reference trong Go lang là gì và khi nào nên truyền con trỏ Pointer thay vì giá trị thông thường?

Junior

Bản chất cơ chế

Trong Go lang, mọi thứ đều được truyền theo cơ chế Pass by Value (Truyền tham trị), bao gồm cả con trỏ (Pointer). Khi bạn truyền một biến vào hàm, Go sẽ tạo một bản sao (copy) của giá trị đó và đưa vào hàm. Nếu truyền một con trỏ, bản sao được tạo ra chính là bản sao của địa chỉ ô nhớ (memory address) chứ không phải bản sao của toàn bộ dữ liệu cấu trúc.

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1147

Làm thế nào để xử lý Race Condition khi nhiều Goroutines cùng truy cập và thay đổi một biến chung trong Go lang?

Junior

Bản chất cơ chế

Race Condition xảy ra khi hai hoặc nhiều Goroutines truy cập cùng một vùng nhớ đồng thời và ít nhất một quyền truy cập là thao tác ghi (write), dẫn đến dữ liệu bị sai lệch hoặc ứng dụng bị crash.

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1148

Làm thế nào để khôi phục lại một commit đã bị xóa nhầm hoặc mất dấu sau khi thực hiện lệnh Git Reset --hard trong môi trường làm việc thực tế?

Junior

Khi lập trình viên thực hiện lệnh git reset --hard không đúng cách, các thay đổi chưa commit hoặc các commit mới tạo có thể biến mất khỏi lịch sử nhánh hiện tại. Để khôi phục lại, chúng ta sử dụng cơ chế Git Reflog.

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1149

Sự khác biệt cốt lõi giữa lệnh Git Fetch và Git Pull là gì và tại sao các lập trình viên cấp độ Junior nên ưu tiên sử dụng Git Fetch trong quy trình làm việc hàng ngày?

Junior

Trong quản lý mã nguồn, việc đồng bộ hóa dữ liệu từ remote repository về local repository là cực kỳ quan trọng. Dưới đây là phân tích chi tiết sự khác biệt giữa hai lệnh này.

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1150

Làm thế nào để xử lý hiệu quả một tình huống Merge Conflict phức tạp xảy ra khi trộn code từ nhánh tính năng vào nhánh phát triển chính?

Junior

Merge Conflict xảy ra khi Git không thể tự động hợp nhất các dòng code do có sự thay đổi chồng chéo trên cùng một vị trí của tệp tin giữa hai nhánh.

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1151

Tại sao việc sử dụng lệnh Git Ignore lại đóng vai trò quan trọng trong việc bảo mật thông tin và tối ưu hóa dung lượng lưu trữ của dự án?

Junior

Tệp .gitignore đóng vai trò định nghĩa các tệp tin và thư mục mà Git sẽ bỏ qua, không theo dõi (track) trong kho lưu trữ mã nguồn.

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1152

Làm thế nào để sửa đổi nội dung hoặc thông điệp của commit gần đây nhất mà không cần tạo thêm một commit mới làm rác lịch sử dự án?

Junior

Trong quá trình phát triển, việc quên thêm một tệp nhỏ hoặc viết sai chính tả trong thông điệp commit gần nhất là rất phổ biến. Thay vì tạo một commit mới với nội dung như 'fix typo', chúng ta sử dụng tính năng Git Amend.

Nội dung chi tiết câu trả lời, phân tích kỹ thuật chuyên sâu, mã nguồn minh họa và các trường hợp ngoại lệ chỉ dành riêng cho học viên Unicode E-learning...

Để mở khóa toàn bộ giải pháp chi tiết và tài liệu hướng dẫn phỏng vấn, vui lòng nâng cấp tài khoản hoặc tham gia gói Learning Pass để truy cập không giới hạn.

// Mã nguồn và kiến trúc giải pháp bị ẩn đối với tài khoản chưa nâng cấp...
1153

Sự khác biệt cốt lõi giữa val và var trong Kotlin là gì và tại sao việc lạm dụng var có thể gây khó khăn trong việc duy trì mã nguồn Enterprise?

Junior

Bản chất cơ chế hoạt động

  • val (value) đại diện cho một tham chiếu chỉ đọc (read-only reference). Khi một biến được khai báo là val, giá trị của nó không thể được gán lại sau khi đã khởi tạo lần đầu (immutable reference). Tuy nhiên, cần lưu ý rằng đối tượng bên trong vẫn có thể thay đổi trạng thái nếu nó là mutable.
  • var (variable) đại diện cho một biến có thể thay đổi giá trị (mutable variable), cho phép gán lại nhiều lần trong vòng đời.

Tác động trong môi trường Enterprise

  • Lạm dụng var làm tăng độ phức tạp của mã nguồn, đặc biệt trong các ứng dụng đa luồng (multi-threaded applications) hoặc kiến trúc hướng sự kiện (event-driven architecture). Khi trạng thái có thể bị thay đổi tự do bởi bất kỳ hàm nào, việc theo dõi luồng dữ liệu (data flow) trở nên khó khăn, dễ dẫn đến các lỗi khó phát hiện như race conditions hoặc side effects không mong muốn.
  • Sử dụng val giúp thúc đẩy lập trình hướng bất biến (immutability), giúp mã nguồn dễ đoán hơn, dễ viết Unit Test và an toàn hơn khi chạy đồng thời.

Ví dụ minh họa

class UserService {
    // Khuyến nghị: Sử dụng val cho các thuộc tính không đổi
    private val maxRetryCount = 3

    fun processUser(userId: String) {
        // Tránh dùng var nếu không thực sự cần thiết gán lại giá trị
        var attempts = 0 
        while (attempts < maxRetryCount) {
            try {
                // Xử lý logic kết nối
                break
            } catch (e: Exception) {
                attempts++
            }
        }
    }
}

Lưu ý kinh nghiệm thực chiến

Ở cấp độ Junior, lập trình viên thường có thói quen dùng var cho mọi biến số vì tính tiện lợi. Trong các dự án Enterprise tại Unicode Academy, chúng tôi luôn yêu cầu ưu tiên tuyệt đối val, và chỉ sử dụng var khi thực sự bắt buộc phải thay đổi trạng thái trong một phạm vi hẹp (local scope).

1154

Làm thế nào để xử lý an toàn NullPointerException trong Kotlin khi tương tác với các thư viện Java cũ (Legacy Java Interoperability)?

Junior

Bản chất cơ chế hoạt động

  • Kotlin được thiết kế để giải quyết triệt để vấn đề Null Safety thông qua hệ thống kiểu phân biệt rõ ràng giữaNullable và Non-null types.
  • Tuy nhiên, khi gọi mã từ Java, Kotlin không thể biết chắc chắn liệu một phương thức Java có trả về giá trị null hay không do Java không có hệ thống Null Safety tương tự. Kotlin giải quyết việc này bằng cách sử dụng Platform Types (ký hiệu bằng dấu chấm hỏi kép T!). Platform Types cho phép lập trình viên tùy ý coi kiểu dữ liệu đó là nullable hoặc non-null.

Các bước xử lý an toàn

  1. Sử dụng Safe Calls (?.): Tránh gọi trực tiếp phương thức trên đối tượng Java nếu chưa chắc chắn nó khác null.
  2. Sử dụng Elvis Operator (?:): Cung cấp giá trị mặc định khi gặp giá trị null.
  3. Sử dụng Not-null Assertion (!!): Chỉ dùng khi tuyệt đối chắc chắn Java trả về giá trị non-null, nếu không sẽ ném ra NullPointerException.
  4. Khai báo Annotation phía Java: Sử dụng các annotation như @NotNull và @Nullable trong mã nguồn Java để Kotlin nhận diện chính xác kiểu dữ liệu.

Ví dụ minh họa

// Giả sử gọi một phương thức từ thư viện Java cũ
val javaUser: JavaUser? = LegacyJavaLibrary.getUser()

// Xử lý an toàn bằng Safe Calls và Elvis Operator
val userName: String = javaUser?.name ?: "Unknown"

// Xử lý khi Java không có annotation
val email = javaUser?.email.orEmpty()

Lưu ý kinh nghiệm thực chiến

Khi tích hợp các thư viện Java trong dự án Enterprise lớn, không bao giờ lạm dụng toán tử !!. Nếu thư viện Java không có sẵn annotation quản lý null, hãy luôn giả định rằng giá trị trả về có thể là null và áp dụng chiến lược phòng thủ mã nguồn (defensive programming).

1155

Sự khác biệt giữa lateinit và lazy trong Kotlin là gì và khi nào nên áp dụng từng cơ chế trong phát triển ứng dụng?

Junior

Bản chất cơ chế hoạt động

  • lateinit var:
    • Dùng cho kiểu dữ liệu biến đổi (var) không phải kiểu nguyên thủy (primitive types như Int, Boolean).
    • Cho phép hoãn thời điểm khởi tạo giá trị của biến sau khi đối tượng đã được khởi tạo (thường dùng trong Dependency Injection hoặc Android Activity/Fragment lifecycle).
    • Nếu truy cập biến lateinit trước khi nó được gán giá trị, hệ thống sẽ ném ra ngoại lệ UninitializedPropertyAccessException.
  • val lazy:
    • Dùng cho thuộc tính chỉ đọc (val).
    • Giá trị chỉ được tính toán và khởi tạo tại lần truy cập đầu tiên (lazy initialization).
    • Mặc định cơ chế thread-safety là LazyThreadSafetyMode.SYNCHRONIZED, đảm bảo chỉ có một luồng thực thi việc khởi tạo.

Bảng so sánh nhanh

  • lateinit: Dùng cho var, khởi tạo thủ công sau, không hỗ trợ kiểu nguyên thủy.
  • lazy: Dùng cho val, tự động khởi tạo khi gọi lần đầu, hỗ trợ mọi kiểu dữ liệu.

Ví dụ minh họa

class DatabaseManager {
    // lateinit dùng khi phụ thuộc vào Dependency Injection
    @Inject
    lateinit var connectionPool: ConnectionPool

    // lazy dùng khi tài nguyên nặng, chỉ khởi tạo khi thực sự cần thiết
    val heavyConfiguration: ConfigData by lazy {
        ConfigData.loadFromDisk()
    }
}

Lưu ý kinh nghiệm thực chiến

Lập trình viên Junior thường hay nhầm lẫn hai khái niệm này. Hãy nhớ nguyên tắc vàng: Dùng lateinit khi bạn biết chắc chắn giá trị sẽ được gán trước khi sử dụng (nhưng chưa thể gán lúc khai báo). Dùng lazy khi bạn muốn tối ưu hóa hiệu năng, hoãn việc tải tài nguyên nặng cho đến thời điểm gọi lần đầu tiên.

High-Ticket Mentoring
Cần Mentor Phỏng Vấn Thử 1-1 & Tối Ưu CV?

Mô phỏng phỏng vấn kỹ thuật thực tế 1-1 qua Google Meet, nhận xét chi tiết điểm mạnh/yếu và sửa CV trực tiếp cùng giảng viên Unicode.

AI Resume Scanner
Kiểm Tra CV Chuẩn ATS Miễn Phí

Tải CV của bạn lên để hệ thống AI rà soát từ khóa kỹ năng, định dạng và tính điểm chuẩn nhà tuyển dụng.

vừa nâng cấp PRO khóa 1 phút trước   Tìm hiểu khóa học