Search
left arrowBack
Pavel Rykov

Pavel Rykov

March 30, 2023 ・ Code

Switching to GoLang from PHP (3 of 3)

In this final part of the tutorial series, we will discuss the benefits of switching from PHP to GoLang and how it can lead to improved performance, concurrency, and ease of deployment in your web applications and APIs. We will also provide some tips for transitioning from PHP to GoLang, as well as a brief discussion on GoLang's goroutines and their advantages.

Benefits of switching to GoLang

GoLang, also known as Go, offers several advantages over PHP:

  • Performance: GoLang is a compiled language, which generally results in faster execution times compared to interpreted languages like PHP. The GoLang runtime is also optimized for better performance and lower memory consumption.

  • Concurrency: GoLang's built-in support for concurrency using goroutines makes it easier to build high-performance, concurrent applications. PHP's support for concurrent programming is limited and requires external libraries or extensions.

  • Static typing: GoLang is a statically typed language, which can help catch errors earlier in the development process and improve code quality.

  • Ease of deployment: GoLang applications can be compiled into a single executable binary, making deployment simple and straightforward. PHP applications often require a separate web server and runtime environment.

  • Smaller Docker containers: GoLang applications can be packaged into small Docker containers, which reduces resource usage and startup times.

Tips for Transitioning from PHP to GoLang

When transitioning from PHP to GoLang, consider the following tips:

  • Learn the GoLang syntax and idiomatic code: GoLang has a different syntax and code style compared to PHP. Invest time in learning the language and familiarizing yourself with best practices.

  • Understand GoLang's type system: GoLang has a strong static type system, which is different from PHP's dynamic typing. Learn about GoLang's basic data types, type inference, and type conversion.

  • Get familiar with GoLang's standard library: GoLang has an extensive standard library that provides a wide range of functionalities. Explore the library to learn about commonly used packages and functions.

  • Leverage GoLang's concurrency model: One of the key strengths of GoLang is its built-in support for concurrency using goroutines and channels. Learn how to use these features effectively to build high-performance applications.

  • Start small: Begin by converting small parts of your PHP application to GoLang, such as utility functions or individual API endpoints. Gradually work your way up to more complex components.

Goroutines in GoLang

Goroutines are lightweight threads managed by the Go runtime. They are a core feature of GoLang and make it easy to build concurrent applications. Goroutines are more efficient than traditional threads because they consume less memory and have lower context-switching overhead.

Here's a simple example of using goroutines in GoLang:

package main

import (
	"fmt"
	"time"
)

func printMessage(message string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(message)
	}
}

func main() {
	go printMessage("Hello")
	go printMessage("World")

	// Wait for goroutines to complete
	time.Sleep(1 * time.Second)
}

In this example, two goroutines are created to print messages concurrently. This is more efficient than using traditional threads or PHP's equivalent, such as pthreads or parallel.

Comparing Docker container sizes for PHP and GoLang

GoLang applications can be compiled into small, self-contained binaries, which can be packaged into smaller Docker containers. This is beneficial for reducing resource usage, improving startup times, and simplifying deployment.

Let's compare the Docker container sizes for a simple PHP application and its GoLang equivalent:

PHP Application Dockerfile

FROM php:7.4-apache

COPY . /var/www/html/
WORKDIR /var/www/html/
RUN composer install

GoLang Application Dockerfile

# Stage 1 - Building
FROM golang:1.20 AS builder
WORKDIR /app
COPY . .
RUN go build -o main .

# Stage 2 - Minimal image
FROM scratch
COPY --from=builder /app/main /main
ENTRYPOINT ["/main"]

The PHP application requires a larger base image (php:7.4-apache) to run, as it includes PHP runtime and Apache web server. On the other hand, the GoLang application uses a multi-stage build, where the binary is compiled in the first stage (golang:1.20), and then the binary is copied to a minimal scratch base image in the second stage. This results in a significantly smaller Docker container for the GoLang application.

In general, GoLang applications can have Docker container sizes that are several times smaller than their PHP counterparts. This reduces resource usage and improves application startup times, especially in containerized environments like Kubernetes or Docker Swarm.

Integrating Prometheus with GoLang Applications

Prometheus is a powerful open-source monitoring and alerting toolkit that is particularly well-suited for monitoring cloud-native applications. Integrating Prometheus into your GoLang application is straightforward, thanks to the extensive support provided by Go's ecosystem and libraries.

In this chapter, we'll walk through the process of adding Prometheus metrics to a GoLang application.

1. Adding Prometheus client library

First, add the Prometheus client library to your GoLang application by running the following command:

go get github.com/prometheus/client_golang/prometheus

2. Creating custom metrics

In your GoLang application, import the prometheus package and create custom metrics for your application. Here's an example of creating a counter and a histogram:

package main

import (
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"net/http"
)

var (
	httpRequestsTotal = prometheus.NewCounterVec(
		prometheus.CounterOpts{
			Name: "http_requests_total",
			Help: "Total number of HTTP requests",
		},
		[]string{"method", "path"},
	)

	requestDuration = prometheus.NewHistogramVec(
		prometheus.HistogramOpts{
			Name:    "request_duration_seconds",
			Help:    "Duration of HTTP requests",
			Buckets: prometheus.LinearBuckets(0.1, 0.1, 10),
		},
		[]string{"method", "path"},
	)
)

func init() {
	prometheus.MustRegister(httpRequestsTotal)
	prometheus.MustRegister(requestDuration)
}

In this example, we've defined a counter (httpRequestsTotal) to track the total number of HTTP requests and a histogram (requestDuration) to measure the duration of HTTP requests.

3. Exposing Prometheus metrics

Next, create a new endpoint in your application to expose the Prometheus metrics. Here's an example of adding a /metrics endpoint to your GoLang application:

func main() {
	http.Handle("/metrics", promhttp.Handler())
	http.ListenAndServe(":8080", nil)
}

4. Instrumenting your application

Now that you've defined and exposed custom metrics, you'll need to instrument your application to update these metrics as needed. Here's an example of how to do this for an HTTP server:

func myHandler(w http.ResponseWriter, r *http.Request) {
	// Update the request counter
	httpRequestsTotal.WithLabelValues(r.Method, r.URL.Path).Inc()

	// Measure the request duration
	timer := prometheus.NewTimer(requestDuration.WithLabelValues(r.Method, r.URL.Path))
	defer timer.ObserveDuration()

	// Your application logic goes here
	w.Write([]byte("Hello, world!"))
}

func main() {
	http.Handle("/metrics", promhttp.Handler())
	http.HandleFunc("/", myHandler)
	http.ListenAndServe(":8080", nil)
}

In this example, we've instrumented the myHandler function to update the httpRequestsTotal counter and measure the request duration using the requestDuration histogram.

5. Configuring Prometheus to scrape metrics

Finally, configure your Prometheus server to scrape the metrics from your GoLang application by updating the prometheus.yml configuration file:

scrape_configs:
  - job_name: 'my_golang_app'
    static_configs:
      - targets: ['<your_golang_app_ip>:8080']

Replace <your_golang_app_ip> with the IP address or hostname of your GoLang application.

With these steps complete, your GoLang application will now expose Prometheus metrics that can be scraped and monitored by a Prometheus server. This integration allows you to gain valuable insights into your application's performance and resource usage, enabling you to optimize and improve its reliability.

Integrating Prometheus with a GoLang application is a prime example of how the Go ecosystem provides developers with the tools and libraries needed for a seamless and efficient development experience. By taking advantage of these resources, you can not only improve your application's performance but also gain better visibility into its inner workings, ultimately leading to more robust and reliable software.

Conclusion

Switching from PHP to GoLang can bring several benefits to your web applications and APIs, including better performance, improved concurrency, and ease of deployment. GoLang's goroutines offer a more efficient approach to concurrent programming compared to PHP's options, and the language's smaller Docker container sizes can lead to more efficient resource usage.

Integrating Prometheus with a GoLang application is a prime example of how the Go ecosystem provides developers with the tools and libraries needed for a seamless and efficient development experience. By taking advantage of these resources, you can not only improve your application's performance but also gain better visibility into its inner workings, ultimately leading to more robust and reliable software.

When transitioning from PHP to GoLang, be prepared to invest time in learning the language, its syntax, and best practices. Start small by converting individual components of your application, and gradually work your way up to more complex parts. With time and practice, you will be able to harness the full potential of GoLang for your web development projects. By embracing GoLang, you can build more efficient and scalable web applications that meet the demands of today's modern, cloud-native environments.

  • Code